diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 13c471f0ee4..3282a21f75f 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -20010,6 +20010,10 @@ } ] }, + "io.k8s.api.scheduling.v1alpha3.AllCompositeDisruptionMode": { + "description": "AllCompositeDisruptionMode means that children of a CompositePodGroup can only be disrupted or preempted together.", + "type": "object" + }, "io.k8s.api.scheduling.v1alpha3.AllDisruptionMode": { "description": "AllDisruptionMode specifies that children can only be disrupted together.", "type": "object" @@ -20022,6 +20026,28 @@ "description": "CompositeBasicSchedulingPolicy indicates that the groups belonging to the composite group should be scheduled independently.", "type": "object" }, + "io.k8s.api.scheduling.v1alpha3.CompositeDisruptionMode": { + "description": "CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. Exactly one mode must be set.", + "properties": { + "all": { + "$ref": "#/definitions/io.k8s.api.scheduling.v1alpha3.AllCompositeDisruptionMode", + "description": "all specifies that all children groups can only be disrupted together." + }, + "single": { + "$ref": "#/definitions/io.k8s.api.scheduling.v1alpha3.SingleCompositeDisruptionMode", + "description": "single specifies that children groups can be disrupted independently from each other." + } + }, + "type": "object", + "x-kubernetes-unions": [ + { + "fields-to-discriminateBy": { + "all": "All", + "single": "Single" + } + } + ] + }, "io.k8s.api.scheduling.v1alpha3.CompositeGangSchedulingPolicy": { "description": "CompositeGangSchedulingPolicy indicates that the groups belonging to the composite group should be scheduled using all-or-nothing semantics.", "properties": { @@ -20146,10 +20172,18 @@ "io.k8s.api.scheduling.v1alpha3.CompositePodGroupSpec": { "description": "CompositePodGroupSpec defines the desired state of CompositePodGroup.", "properties": { + "disruptionMode": { + "$ref": "#/definitions/io.k8s.api.scheduling.v1alpha3.CompositeDisruptionMode", + "description": "disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. One of Single, All. Defaults to Single if unset. This field is immutable." + }, "parentCompositePodGroupName": { "description": "parentCompositePodGroupName contains the name of the parent composite pod group within the same namespace as this composite pod group. It must be a DNS name. If it's nil, then this composite pod group is a root of a workload's hierarchy. This field is immutable.", "type": "string" }, + "preemptionPolicy": { + "description": "preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. When Priority Admission Controller is enabled, it populates this field from PriorityClassName, and defaults to PreemptLowerPriority if value is unset in PriorityClass. This field is immutable. This field is available only when the PodGroupPreemptionPolicy feature gate is enabled.", + "type": "string" + }, "priority": { "description": "priority is the value of priority of this composite pod group. Various system components use this field to find the priority of the composite pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.", "format": "int32", @@ -20211,6 +20245,10 @@ ], "x-kubernetes-list-type": "map" }, + "disruptionMode": { + "$ref": "#/definitions/io.k8s.api.scheduling.v1alpha3.CompositeDisruptionMode", + "description": "disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. One of Single, All. This field is immutable." + }, "name": { "description": "name is a unique identifier for the CompositePodGroupTemplate within the Workload. It must be a DNS label. This field is required.", "type": "string" @@ -20226,6 +20264,10 @@ ], "x-kubernetes-list-type": "map" }, + "preemptionPolicy": { + "description": "preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. One of Never, PreemptLowerPriority. This field is immutable. This field is available only when the PodGroupPreemptionPolicy feature gate is enabled.", + "type": "string" + }, "priority": { "description": "priority is the value of priority of composite pod groups created from this template. Various system components use this field to find the priority of the composite pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.", "format": "int32", @@ -20570,6 +20612,10 @@ ], "type": "object" }, + "io.k8s.api.scheduling.v1alpha3.SingleCompositeDisruptionMode": { + "description": "SingleCompositeDisruptionMode means that individual children of a CompositePodGroup can be disrupted or preempted independently.", + "type": "object" + }, "io.k8s.api.scheduling.v1alpha3.SingleDisruptionMode": { "description": "SingleDisruptionMode specifies that children can be disrupted independently.", "type": "object" @@ -20828,6 +20874,10 @@ }, "type": "object" }, + "io.k8s.api.scheduling.v1beta1.AllCompositeDisruptionMode": { + "description": "AllCompositeDisruptionMode means that children of a CompositePodGroup can only be disrupted or preempted together.", + "type": "object" + }, "io.k8s.api.scheduling.v1beta1.AllDisruptionMode": { "description": "AllDisruptionMode specifies that children can only be disrupted together.", "type": "object" @@ -20840,6 +20890,28 @@ "description": "CompositeBasicSchedulingPolicy indicates that the groups belonging to the composite group should be scheduled independently.", "type": "object" }, + "io.k8s.api.scheduling.v1beta1.CompositeDisruptionMode": { + "description": "CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. Exactly one mode must be set.", + "properties": { + "all": { + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.AllCompositeDisruptionMode", + "description": "all specifies that all children groups can only be disrupted together." + }, + "single": { + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.SingleCompositeDisruptionMode", + "description": "single specifies that children groups can be disrupted independently from each other." + } + }, + "type": "object", + "x-kubernetes-unions": [ + { + "fields-to-discriminateBy": { + "all": "All", + "single": "Single" + } + } + ] + }, "io.k8s.api.scheduling.v1beta1.CompositeGangSchedulingPolicy": { "description": "CompositeGangSchedulingPolicy indicates that the groups belonging to the composite group should be scheduled using all-or-nothing semantics.", "properties": { @@ -20904,6 +20976,10 @@ ], "x-kubernetes-list-type": "map" }, + "disruptionMode": { + "$ref": "#/definitions/io.k8s.api.scheduling.v1beta1.CompositeDisruptionMode", + "description": "disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. One of Single, All. This field is immutable." + }, "name": { "description": "name is a unique identifier for the CompositePodGroupTemplate within the Workload. It must be a DNS label. This field is required.", "type": "string" @@ -20919,6 +20995,10 @@ ], "x-kubernetes-list-type": "map" }, + "preemptionPolicy": { + "description": "preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. One of Never, PreemptLowerPriority. This field is immutable. This field is available only when the PodGroupPreemptionPolicy feature gate is enabled.", + "type": "string" + }, "priority": { "description": "priority is the value of priority of composite pod groups created from this template. Various system components use this field to find the priority of the composite pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.", "format": "int32", @@ -21263,6 +21343,10 @@ ], "type": "object" }, + "io.k8s.api.scheduling.v1beta1.SingleCompositeDisruptionMode": { + "description": "SingleCompositeDisruptionMode means that individual children of a CompositePodGroup can be disrupted or preempted independently.", + "type": "object" + }, "io.k8s.api.scheduling.v1beta1.SingleDisruptionMode": { "description": "SingleDisruptionMode specifies that children can be disrupted independently.", "type": "object" diff --git a/api/openapi-spec/v3/apis__scheduling.k8s.io__v1alpha3_openapi.json b/api/openapi-spec/v3/apis__scheduling.k8s.io__v1alpha3_openapi.json index 7ff47d97813..6c50d0c0993 100644 --- a/api/openapi-spec/v3/apis__scheduling.k8s.io__v1alpha3_openapi.json +++ b/api/openapi-spec/v3/apis__scheduling.k8s.io__v1alpha3_openapi.json @@ -1,6 +1,10 @@ { "components": { "schemas": { + "io.k8s.api.scheduling.v1alpha3.AllCompositeDisruptionMode": { + "description": "AllCompositeDisruptionMode means that children of a CompositePodGroup can only be disrupted or preempted together.", + "type": "object" + }, "io.k8s.api.scheduling.v1alpha3.AllDisruptionMode": { "description": "AllDisruptionMode specifies that children can only be disrupted together.", "type": "object" @@ -13,6 +17,36 @@ "description": "CompositeBasicSchedulingPolicy indicates that the groups belonging to the composite group should be scheduled independently.", "type": "object" }, + "io.k8s.api.scheduling.v1alpha3.CompositeDisruptionMode": { + "description": "CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. Exactly one mode must be set.", + "properties": { + "all": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.scheduling.v1alpha3.AllCompositeDisruptionMode" + } + ], + "description": "all specifies that all children groups can only be disrupted together." + }, + "single": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.scheduling.v1alpha3.SingleCompositeDisruptionMode" + } + ], + "description": "single specifies that children groups can be disrupted independently from each other." + } + }, + "type": "object", + "x-kubernetes-unions": [ + { + "fields-to-discriminateBy": { + "all": "All", + "single": "Single" + } + } + ] + }, "io.k8s.api.scheduling.v1alpha3.CompositeGangSchedulingPolicy": { "description": "CompositeGangSchedulingPolicy indicates that the groups belonging to the composite group should be scheduled using all-or-nothing semantics.", "properties": { @@ -166,10 +200,25 @@ "io.k8s.api.scheduling.v1alpha3.CompositePodGroupSpec": { "description": "CompositePodGroupSpec defines the desired state of CompositePodGroup.", "properties": { + "disruptionMode": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.scheduling.v1alpha3.CompositeDisruptionMode" + } + ], + "default": { + "single": {} + }, + "description": "disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. One of Single, All. Defaults to Single if unset. This field is immutable." + }, "parentCompositePodGroupName": { "description": "parentCompositePodGroupName contains the name of the parent composite pod group within the same namespace as this composite pod group. It must be a DNS name. If it's nil, then this composite pod group is a root of a workload's hierarchy. This field is immutable.", "type": "string" }, + "preemptionPolicy": { + "description": "preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. When Priority Admission Controller is enabled, it populates this field from PriorityClassName, and defaults to PreemptLowerPriority if value is unset in PriorityClass. This field is immutable. This field is available only when the PodGroupPreemptionPolicy feature gate is enabled.", + "type": "string" + }, "priority": { "description": "priority is the value of priority of this composite pod group. Various system components use this field to find the priority of the composite pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.", "format": "int32", @@ -244,6 +293,14 @@ ], "x-kubernetes-list-type": "map" }, + "disruptionMode": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.scheduling.v1alpha3.CompositeDisruptionMode" + } + ], + "description": "disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. One of Single, All. This field is immutable." + }, "name": { "default": "", "description": "name is a unique identifier for the CompositePodGroupTemplate within the Workload. It must be a DNS label. This field is required.", @@ -260,6 +317,10 @@ ], "x-kubernetes-list-type": "map" }, + "preemptionPolicy": { + "description": "preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. One of Never, PreemptLowerPriority. This field is immutable. This field is available only when the PodGroupPreemptionPolicy feature gate is enabled.", + "type": "string" + }, "priority": { "description": "priority is the value of priority of composite pod groups created from this template. Various system components use this field to find the priority of the composite pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.", "format": "int32", @@ -686,6 +747,10 @@ ], "type": "object" }, + "io.k8s.api.scheduling.v1alpha3.SingleCompositeDisruptionMode": { + "description": "SingleCompositeDisruptionMode means that individual children of a CompositePodGroup can be disrupted or preempted independently.", + "type": "object" + }, "io.k8s.api.scheduling.v1alpha3.SingleDisruptionMode": { "description": "SingleDisruptionMode specifies that children can be disrupted independently.", "type": "object" diff --git a/api/openapi-spec/v3/apis__scheduling.k8s.io__v1beta1_openapi.json b/api/openapi-spec/v3/apis__scheduling.k8s.io__v1beta1_openapi.json index 8238920e7b7..a66830c2404 100644 --- a/api/openapi-spec/v3/apis__scheduling.k8s.io__v1beta1_openapi.json +++ b/api/openapi-spec/v3/apis__scheduling.k8s.io__v1beta1_openapi.json @@ -1,6 +1,10 @@ { "components": { "schemas": { + "io.k8s.api.scheduling.v1beta1.AllCompositeDisruptionMode": { + "description": "AllCompositeDisruptionMode means that children of a CompositePodGroup can only be disrupted or preempted together.", + "type": "object" + }, "io.k8s.api.scheduling.v1beta1.AllDisruptionMode": { "description": "AllDisruptionMode specifies that children can only be disrupted together.", "type": "object" @@ -13,6 +17,36 @@ "description": "CompositeBasicSchedulingPolicy indicates that the groups belonging to the composite group should be scheduled independently.", "type": "object" }, + "io.k8s.api.scheduling.v1beta1.CompositeDisruptionMode": { + "description": "CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. Exactly one mode must be set.", + "properties": { + "all": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.scheduling.v1beta1.AllCompositeDisruptionMode" + } + ], + "description": "all specifies that all children groups can only be disrupted together." + }, + "single": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.scheduling.v1beta1.SingleCompositeDisruptionMode" + } + ], + "description": "single specifies that children groups can be disrupted independently from each other." + } + }, + "type": "object", + "x-kubernetes-unions": [ + { + "fields-to-discriminateBy": { + "all": "All", + "single": "Single" + } + } + ] + }, "io.k8s.api.scheduling.v1beta1.CompositeGangSchedulingPolicy": { "description": "CompositeGangSchedulingPolicy indicates that the groups belonging to the composite group should be scheduled using all-or-nothing semantics.", "properties": { @@ -86,6 +120,14 @@ ], "x-kubernetes-list-type": "map" }, + "disruptionMode": { + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.api.scheduling.v1beta1.CompositeDisruptionMode" + } + ], + "description": "disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. One of Single, All. This field is immutable." + }, "name": { "default": "", "description": "name is a unique identifier for the CompositePodGroupTemplate within the Workload. It must be a DNS label. This field is required.", @@ -102,6 +144,10 @@ ], "x-kubernetes-list-type": "map" }, + "preemptionPolicy": { + "description": "preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. One of Never, PreemptLowerPriority. This field is immutable. This field is available only when the PodGroupPreemptionPolicy feature gate is enabled.", + "type": "string" + }, "priority": { "description": "priority is the value of priority of composite pod groups created from this template. Various system components use this field to find the priority of the composite pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.", "format": "int32", @@ -528,6 +574,10 @@ ], "type": "object" }, + "io.k8s.api.scheduling.v1beta1.SingleCompositeDisruptionMode": { + "description": "SingleCompositeDisruptionMode means that individual children of a CompositePodGroup can be disrupted or preempted independently.", + "type": "object" + }, "io.k8s.api.scheduling.v1beta1.SingleDisruptionMode": { "description": "SingleDisruptionMode specifies that children can be disrupted independently.", "type": "object" diff --git a/pkg/api/testing/defaulting_test.go b/pkg/api/testing/defaulting_test.go index ea635893829..bcfe1c6b977 100644 --- a/pkg/api/testing/defaulting_test.go +++ b/pkg/api/testing/defaulting_test.go @@ -227,6 +227,8 @@ func TestDefaulting(t *testing.T) { {Group: "scheduling.k8s.io", Version: "v1alpha3", Kind: "PodGroupList"}: {}, {Group: "scheduling.k8s.io", Version: "v1beta1", Kind: "PodGroup"}: {}, {Group: "scheduling.k8s.io", Version: "v1beta1", Kind: "PodGroupList"}: {}, + {Group: "scheduling.k8s.io", Version: "v1alpha3", Kind: "CompositePodGroup"}: {}, + {Group: "scheduling.k8s.io", Version: "v1alpha3", Kind: "CompositePodGroupList"}: {}, {Group: "scheduling.k8s.io", Version: "v1beta1", Kind: "PriorityClass"}: {}, {Group: "scheduling.k8s.io", Version: "v1", Kind: "PriorityClass"}: {}, {Group: "scheduling.k8s.io", Version: "v1beta1", Kind: "PriorityClassList"}: {}, diff --git a/pkg/apis/scheduling/fuzzer/fuzzer.go b/pkg/apis/scheduling/fuzzer/fuzzer.go index 07b3ce7a5ee..ba0ec06a3f0 100644 --- a/pkg/apis/scheduling/fuzzer/fuzzer.go +++ b/pkg/apis/scheduling/fuzzer/fuzzer.go @@ -43,5 +43,15 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { s.Spec.PreemptionPolicy = &preemptLowerPriority } }, + func(s *scheduling.CompositePodGroup, c randfill.Continue) { + c.FillNoCustom(s) + if s.Spec.DisruptionMode == nil { + s.Spec.DisruptionMode = &scheduling.CompositeDisruptionMode{Single: &scheduling.SingleCompositeDisruptionMode{}} + } + if s.Spec.PreemptionPolicy == nil { + preemptLowerPriority := scheduling.PreemptLowerPriority + s.Spec.PreemptionPolicy = &preemptLowerPriority + } + }, } } diff --git a/pkg/apis/scheduling/types.go b/pkg/apis/scheduling/types.go index 7c0cec23493..a39e88825f9 100644 --- a/pkg/apis/scheduling/types.go +++ b/pkg/apis/scheduling/types.go @@ -288,6 +288,19 @@ type CompositePodGroupTemplate struct { // +required SchedulingPolicy CompositePodGroupSchedulingPolicy + // SchedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. + // This field is immutable. + // + // +optional + SchedulingConstraints *CompositePodGroupSchedulingConstraints + + // DisruptionMode defines the mode in which a given CompositePodGroup can be disrupted. + // One of Single, All. + // This field is immutable. + // + // +optional + DisruptionMode *CompositeDisruptionMode + // PriorityClassName indicates the priority that should be considered when scheduling // a composite pod group created from this template. If no priority class is specified, // admission control can set this to the global default priority class if it exists. @@ -308,6 +321,15 @@ type CompositePodGroupTemplate struct { // +optional Priority *int32 + // PreemptionPolicy is the Policy for preempting pods/podgroups with lower priority. + // One of Never, PreemptLowerPriority. + // This field is immutable. + // This field is available only when the PodGroupPreemptionPolicy feature gate is enabled. + // + // +featureGate=PodGroupPreemptionPolicy + // +optional + PreemptionPolicy *PreemptionPolicy + // PodGroupTemplates is the list of templates for children PodGroups. // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates // or PodGroupTemplates must be set. @@ -325,12 +347,6 @@ type CompositePodGroupTemplate struct { // +listType=map // +listMapKey=name CompositePodGroupTemplates []CompositePodGroupTemplate - - // SchedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. - // This field is immutable. - // - // +optional - SchedulingConstraints *CompositePodGroupSchedulingConstraints } // PodGroupSchedulingPolicy defines the scheduling configuration for a PodGroup. @@ -771,6 +787,21 @@ type CompositePodGroupSpec struct { // +required SchedulingPolicy CompositePodGroupSchedulingPolicy + // SchedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroup. + // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. + // This field is immutable. + // + // +optional + SchedulingConstraints *CompositePodGroupSchedulingConstraints + + // DisruptionMode defines the mode in which a given CompositePodGroup can be disrupted. + // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. + // One of Single, All. Defaults to Single if unset. + // This field is immutable. + // + // +optional + DisruptionMode *CompositeDisruptionMode + // PriorityClassName defines the priority that should be considered when scheduling this CompositePodGroup. // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. // If left unspecified, it is validated and resolved similarly to the PriorityClassName field in Pods @@ -791,12 +822,16 @@ type CompositePodGroupSpec struct { // +optional Priority *int32 - // SchedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroup. - // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. + // PreemptionPolicy is the Policy for preempting pods/podgroups with lower priority. + // One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. + // When Priority Admission Controller is enabled, it populates this field from PriorityClassName, + // and defaults to PreemptLowerPriority if value is unset in PriorityClass. // This field is immutable. + // This field is available only when the PodGroupPreemptionPolicy feature gate is enabled. // + // +featureGate=PodGroupPreemptionPolicy // +optional - SchedulingConstraints *CompositePodGroupSchedulingConstraints + PreemptionPolicy *PreemptionPolicy } // CompositePodGroupSchedulingPolicy defines the scheduling configuration for a CompositePodGroup. @@ -837,6 +872,34 @@ type CompositeGangSchedulingPolicy struct { MinGroupCount int32 } +// CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. +// Exactly one mode must be set. +// +// +union +type CompositeDisruptionMode struct { + // Single specifies that children groups can be disrupted independently from each other. + // + // +optional + Single *SingleCompositeDisruptionMode + + // All specifies that all children groups can only be disrupted together. + // + // +optional + All *AllCompositeDisruptionMode +} + +// SingleCompositeDisruptionMode means that individual children of a CompositePodGroup +// can be disrupted or preempted independently. +type SingleCompositeDisruptionMode struct { + // This is intentionally empty. +} + +// AllCompositeDisruptionMode means that children of a CompositePodGroup can only be +// disrupted or preempted together. +type AllCompositeDisruptionMode struct { + // This is intentionally empty. +} + // CompositePodGroupStatus represents information about the status of a composite pod group. type CompositePodGroupStatus struct { // Conditions represent the latest observations of the CompositePodGroup's state. diff --git a/pkg/apis/scheduling/v1alpha3/defaults.go b/pkg/apis/scheduling/v1alpha3/defaults.go index fdd44a0ff64..70aab0e5b72 100644 --- a/pkg/apis/scheduling/v1alpha3/defaults.go +++ b/pkg/apis/scheduling/v1alpha3/defaults.go @@ -35,3 +35,12 @@ func SetDefaults_PodGroup(in *schedulingv1alpha3.PodGroup) { } } } + +func SetDefaults_CompositePodGroup(in *schedulingv1alpha3.CompositePodGroup) { + if utilfeature.DefaultFeatureGate.Enabled(features.PodGroupPreemptionPolicy) { + if in.Spec.PreemptionPolicy == nil { + preemptLowerPriority := schedulingv1alpha3.PreemptLowerPriority + in.Spec.PreemptionPolicy = &preemptLowerPriority + } + } +} diff --git a/pkg/apis/scheduling/v1alpha3/zz_generated.conversion.go b/pkg/apis/scheduling/v1alpha3/zz_generated.conversion.go index 99b79511520..9a008f3612f 100644 --- a/pkg/apis/scheduling/v1alpha3/zz_generated.conversion.go +++ b/pkg/apis/scheduling/v1alpha3/zz_generated.conversion.go @@ -37,6 +37,16 @@ func init() { // RegisterConversions adds conversion functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*schedulingv1alpha3.AllCompositeDisruptionMode)(nil), (*scheduling.AllCompositeDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_AllCompositeDisruptionMode_To_scheduling_AllCompositeDisruptionMode(a.(*schedulingv1alpha3.AllCompositeDisruptionMode), b.(*scheduling.AllCompositeDisruptionMode), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheduling.AllCompositeDisruptionMode)(nil), (*schedulingv1alpha3.AllCompositeDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheduling_AllCompositeDisruptionMode_To_v1alpha3_AllCompositeDisruptionMode(a.(*scheduling.AllCompositeDisruptionMode), b.(*schedulingv1alpha3.AllCompositeDisruptionMode), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*schedulingv1alpha3.AllDisruptionMode)(nil), (*scheduling.AllDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha3_AllDisruptionMode_To_scheduling_AllDisruptionMode(a.(*schedulingv1alpha3.AllDisruptionMode), b.(*scheduling.AllDisruptionMode), scope) }); err != nil { @@ -67,6 +77,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*schedulingv1alpha3.CompositeDisruptionMode)(nil), (*scheduling.CompositeDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_CompositeDisruptionMode_To_scheduling_CompositeDisruptionMode(a.(*schedulingv1alpha3.CompositeDisruptionMode), b.(*scheduling.CompositeDisruptionMode), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheduling.CompositeDisruptionMode)(nil), (*schedulingv1alpha3.CompositeDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheduling_CompositeDisruptionMode_To_v1alpha3_CompositeDisruptionMode(a.(*scheduling.CompositeDisruptionMode), b.(*schedulingv1alpha3.CompositeDisruptionMode), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*schedulingv1alpha3.CompositeGangSchedulingPolicy)(nil), (*scheduling.CompositeGangSchedulingPolicy)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha3_CompositeGangSchedulingPolicy_To_scheduling_CompositeGangSchedulingPolicy(a.(*schedulingv1alpha3.CompositeGangSchedulingPolicy), b.(*scheduling.CompositeGangSchedulingPolicy), scope) }); err != nil { @@ -257,6 +277,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*schedulingv1alpha3.SingleCompositeDisruptionMode)(nil), (*scheduling.SingleCompositeDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_SingleCompositeDisruptionMode_To_scheduling_SingleCompositeDisruptionMode(a.(*schedulingv1alpha3.SingleCompositeDisruptionMode), b.(*scheduling.SingleCompositeDisruptionMode), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheduling.SingleCompositeDisruptionMode)(nil), (*schedulingv1alpha3.SingleCompositeDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheduling_SingleCompositeDisruptionMode_To_v1alpha3_SingleCompositeDisruptionMode(a.(*scheduling.SingleCompositeDisruptionMode), b.(*schedulingv1alpha3.SingleCompositeDisruptionMode), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*schedulingv1alpha3.SingleDisruptionMode)(nil), (*scheduling.SingleDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha3_SingleDisruptionMode_To_scheduling_SingleDisruptionMode(a.(*schedulingv1alpha3.SingleDisruptionMode), b.(*scheduling.SingleDisruptionMode), scope) }); err != nil { @@ -330,6 +360,26 @@ func RegisterConversions(s *runtime.Scheme) error { return nil } +func autoConvert_v1alpha3_AllCompositeDisruptionMode_To_scheduling_AllCompositeDisruptionMode(in *schedulingv1alpha3.AllCompositeDisruptionMode, out *scheduling.AllCompositeDisruptionMode, s conversion.Scope) error { + *out = *(*scheduling.AllCompositeDisruptionMode)(unsafe.Pointer(in)) + return nil +} + +// Convert_v1alpha3_AllCompositeDisruptionMode_To_scheduling_AllCompositeDisruptionMode is an autogenerated conversion function. +func Convert_v1alpha3_AllCompositeDisruptionMode_To_scheduling_AllCompositeDisruptionMode(in *schedulingv1alpha3.AllCompositeDisruptionMode, out *scheduling.AllCompositeDisruptionMode, s conversion.Scope) error { + return autoConvert_v1alpha3_AllCompositeDisruptionMode_To_scheduling_AllCompositeDisruptionMode(in, out, s) +} + +func autoConvert_scheduling_AllCompositeDisruptionMode_To_v1alpha3_AllCompositeDisruptionMode(in *scheduling.AllCompositeDisruptionMode, out *schedulingv1alpha3.AllCompositeDisruptionMode, s conversion.Scope) error { + *out = *(*schedulingv1alpha3.AllCompositeDisruptionMode)(unsafe.Pointer(in)) + return nil +} + +// Convert_scheduling_AllCompositeDisruptionMode_To_v1alpha3_AllCompositeDisruptionMode is an autogenerated conversion function. +func Convert_scheduling_AllCompositeDisruptionMode_To_v1alpha3_AllCompositeDisruptionMode(in *scheduling.AllCompositeDisruptionMode, out *schedulingv1alpha3.AllCompositeDisruptionMode, s conversion.Scope) error { + return autoConvert_scheduling_AllCompositeDisruptionMode_To_v1alpha3_AllCompositeDisruptionMode(in, out, s) +} + func autoConvert_v1alpha3_AllDisruptionMode_To_scheduling_AllDisruptionMode(in *schedulingv1alpha3.AllDisruptionMode, out *scheduling.AllDisruptionMode, s conversion.Scope) error { *out = *(*scheduling.AllDisruptionMode)(unsafe.Pointer(in)) return nil @@ -390,6 +440,26 @@ func Convert_scheduling_CompositeBasicSchedulingPolicy_To_v1alpha3_CompositeBasi return autoConvert_scheduling_CompositeBasicSchedulingPolicy_To_v1alpha3_CompositeBasicSchedulingPolicy(in, out, s) } +func autoConvert_v1alpha3_CompositeDisruptionMode_To_scheduling_CompositeDisruptionMode(in *schedulingv1alpha3.CompositeDisruptionMode, out *scheduling.CompositeDisruptionMode, s conversion.Scope) error { + *out = *(*scheduling.CompositeDisruptionMode)(unsafe.Pointer(in)) + return nil +} + +// Convert_v1alpha3_CompositeDisruptionMode_To_scheduling_CompositeDisruptionMode is an autogenerated conversion function. +func Convert_v1alpha3_CompositeDisruptionMode_To_scheduling_CompositeDisruptionMode(in *schedulingv1alpha3.CompositeDisruptionMode, out *scheduling.CompositeDisruptionMode, s conversion.Scope) error { + return autoConvert_v1alpha3_CompositeDisruptionMode_To_scheduling_CompositeDisruptionMode(in, out, s) +} + +func autoConvert_scheduling_CompositeDisruptionMode_To_v1alpha3_CompositeDisruptionMode(in *scheduling.CompositeDisruptionMode, out *schedulingv1alpha3.CompositeDisruptionMode, s conversion.Scope) error { + *out = *(*schedulingv1alpha3.CompositeDisruptionMode)(unsafe.Pointer(in)) + return nil +} + +// Convert_scheduling_CompositeDisruptionMode_To_v1alpha3_CompositeDisruptionMode is an autogenerated conversion function. +func Convert_scheduling_CompositeDisruptionMode_To_v1alpha3_CompositeDisruptionMode(in *scheduling.CompositeDisruptionMode, out *schedulingv1alpha3.CompositeDisruptionMode, s conversion.Scope) error { + return autoConvert_scheduling_CompositeDisruptionMode_To_v1alpha3_CompositeDisruptionMode(in, out, s) +} + func autoConvert_v1alpha3_CompositeGangSchedulingPolicy_To_scheduling_CompositeGangSchedulingPolicy(in *schedulingv1alpha3.CompositeGangSchedulingPolicy, out *scheduling.CompositeGangSchedulingPolicy, s conversion.Scope) error { *out = *(*scheduling.CompositeGangSchedulingPolicy)(unsafe.Pointer(in)) return nil @@ -798,6 +868,26 @@ func Convert_scheduling_PodGroupTemplate_To_v1alpha3_PodGroupTemplate(in *schedu return autoConvert_scheduling_PodGroupTemplate_To_v1alpha3_PodGroupTemplate(in, out, s) } +func autoConvert_v1alpha3_SingleCompositeDisruptionMode_To_scheduling_SingleCompositeDisruptionMode(in *schedulingv1alpha3.SingleCompositeDisruptionMode, out *scheduling.SingleCompositeDisruptionMode, s conversion.Scope) error { + *out = *(*scheduling.SingleCompositeDisruptionMode)(unsafe.Pointer(in)) + return nil +} + +// Convert_v1alpha3_SingleCompositeDisruptionMode_To_scheduling_SingleCompositeDisruptionMode is an autogenerated conversion function. +func Convert_v1alpha3_SingleCompositeDisruptionMode_To_scheduling_SingleCompositeDisruptionMode(in *schedulingv1alpha3.SingleCompositeDisruptionMode, out *scheduling.SingleCompositeDisruptionMode, s conversion.Scope) error { + return autoConvert_v1alpha3_SingleCompositeDisruptionMode_To_scheduling_SingleCompositeDisruptionMode(in, out, s) +} + +func autoConvert_scheduling_SingleCompositeDisruptionMode_To_v1alpha3_SingleCompositeDisruptionMode(in *scheduling.SingleCompositeDisruptionMode, out *schedulingv1alpha3.SingleCompositeDisruptionMode, s conversion.Scope) error { + *out = *(*schedulingv1alpha3.SingleCompositeDisruptionMode)(unsafe.Pointer(in)) + return nil +} + +// Convert_scheduling_SingleCompositeDisruptionMode_To_v1alpha3_SingleCompositeDisruptionMode is an autogenerated conversion function. +func Convert_scheduling_SingleCompositeDisruptionMode_To_v1alpha3_SingleCompositeDisruptionMode(in *scheduling.SingleCompositeDisruptionMode, out *schedulingv1alpha3.SingleCompositeDisruptionMode, s conversion.Scope) error { + return autoConvert_scheduling_SingleCompositeDisruptionMode_To_v1alpha3_SingleCompositeDisruptionMode(in, out, s) +} + func autoConvert_v1alpha3_SingleDisruptionMode_To_scheduling_SingleDisruptionMode(in *schedulingv1alpha3.SingleDisruptionMode, out *scheduling.SingleDisruptionMode, s conversion.Scope) error { *out = *(*scheduling.SingleDisruptionMode)(unsafe.Pointer(in)) return nil diff --git a/pkg/apis/scheduling/v1alpha3/zz_generated.defaults.go b/pkg/apis/scheduling/v1alpha3/zz_generated.defaults.go index b2264ce83ad..a93c5691753 100644 --- a/pkg/apis/scheduling/v1alpha3/zz_generated.defaults.go +++ b/pkg/apis/scheduling/v1alpha3/zz_generated.defaults.go @@ -32,11 +32,33 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { + scheme.AddTypeDefaultingFunc(&schedulingv1alpha3.CompositePodGroup{}, func(obj interface{}) { + SetObjectDefaults_CompositePodGroup(obj.(*schedulingv1alpha3.CompositePodGroup)) + }) + scheme.AddTypeDefaultingFunc(&schedulingv1alpha3.CompositePodGroupList{}, func(obj interface{}) { + SetObjectDefaults_CompositePodGroupList(obj.(*schedulingv1alpha3.CompositePodGroupList)) + }) scheme.AddTypeDefaultingFunc(&schedulingv1alpha3.PodGroup{}, func(obj interface{}) { SetObjectDefaults_PodGroup(obj.(*schedulingv1alpha3.PodGroup)) }) scheme.AddTypeDefaultingFunc(&schedulingv1alpha3.PodGroupList{}, func(obj interface{}) { SetObjectDefaults_PodGroupList(obj.(*schedulingv1alpha3.PodGroupList)) }) return nil } +func SetObjectDefaults_CompositePodGroup(in *schedulingv1alpha3.CompositePodGroup) { + SetDefaults_CompositePodGroup(in) + if in.Spec.DisruptionMode == nil { + if err := json.Unmarshal([]byte(`{"single": {}}`), &in.Spec.DisruptionMode); err != nil { + panic(err) + } + } +} + +func SetObjectDefaults_CompositePodGroupList(in *schedulingv1alpha3.CompositePodGroupList) { + for i := range in.Items { + a := &in.Items[i] + SetObjectDefaults_CompositePodGroup(a) + } +} + func SetObjectDefaults_PodGroup(in *schedulingv1alpha3.PodGroup) { SetDefaults_PodGroup(in) if in.Spec.DisruptionMode == nil { diff --git a/pkg/apis/scheduling/v1alpha3/zz_generated.validations.go b/pkg/apis/scheduling/v1alpha3/zz_generated.validations.go index 37ce0daab20..0f3fd32231e 100644 --- a/pkg/apis/scheduling/v1alpha3/zz_generated.validations.go +++ b/pkg/apis/scheduling/v1alpha3/zz_generated.validations.go @@ -90,6 +90,89 @@ func RegisterValidations(scheme *runtime.Scheme) error { return nil } +var unionMembershipFor_k8s_io_api_scheduling_v1alpha3_CompositeDisruptionMode_ = validate.NewUnionMembership(validate.NewUnionMember("single"), validate.NewUnionMember("all")) + +// Validate_CompositeDisruptionMode validates an instance of CompositeDisruptionMode according +// to declarative validation rules in the API schema. +func Validate_CompositeDisruptionMode( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *schedulingv1alpha3.CompositeDisruptionMode) (errs field.ErrorList) { + + if e := validate.Union(ctx, op, fldPath, obj, oldObj, unionMembershipFor_k8s_io_api_scheduling_v1alpha3_CompositeDisruptionMode_, + func(obj *schedulingv1alpha3.CompositeDisruptionMode) bool { + if obj == nil { + return false + } + return obj.Single != nil + }, + func(obj *schedulingv1alpha3.CompositeDisruptionMode) bool { + if obj == nil { + return false + } + return obj.All != nil + }); len(e) != 0 { + errs = append(errs, e...) + } + + { // field schedulingv1alpha3.CompositeDisruptionMode.Single + fn := func( + fldPath *field.Path, + obj, oldObj *schedulingv1alpha3.SingleCompositeDisruptionMode, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *schedulingv1alpha3.CompositeDisruptionMode) *schedulingv1alpha3.SingleCompositeDisruptionMode { + return oldObj.Single + }) + errs = append(errs, fn(fldPath.Child("single"), obj.Single, oldVal, oldObj != nil)...) + } + + { // field schedulingv1alpha3.CompositeDisruptionMode.All + fn := func( + fldPath *field.Path, + obj, oldObj *schedulingv1alpha3.AllCompositeDisruptionMode, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *schedulingv1alpha3.CompositeDisruptionMode) *schedulingv1alpha3.AllCompositeDisruptionMode { + return oldObj.All + }) + errs = append(errs, fn(fldPath.Child("all"), obj.All, oldVal, oldObj != nil)...) + } + + return errs +} + // Validate_CompositeGangSchedulingPolicy validates an instance of CompositeGangSchedulingPolicy according // to declarative validation rules in the API schema. func Validate_CompositeGangSchedulingPolicy( @@ -453,6 +536,76 @@ func Validate_CompositePodGroupSpec( errs = append(errs, fn(fldPath.Child("schedulingPolicy"), &obj.SchedulingPolicy, oldVal, oldObj != nil)...) } + { // field schedulingv1alpha3.CompositePodGroupSpec.SchedulingConstraints + fn := func( + fldPath *field.Path, + obj, oldObj *schedulingv1alpha3.CompositePodGroupSchedulingConstraints, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_CompositePodGroupSchedulingConstraints(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *schedulingv1alpha3.CompositePodGroupSpec) *schedulingv1alpha3.CompositePodGroupSchedulingConstraints { + return oldObj.SchedulingConstraints + }) + errs = append(errs, fn(fldPath.Child("schedulingConstraints"), obj.SchedulingConstraints, oldVal, oldObj != nil)...) + } + + { // field schedulingv1alpha3.CompositePodGroupSpec.DisruptionMode + fn := func( + fldPath *field.Path, + obj, oldObj *schedulingv1alpha3.CompositeDisruptionMode, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + // optional fields with default values are effectively required + if e := validate.RequiredPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_CompositeDisruptionMode(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *schedulingv1alpha3.CompositePodGroupSpec) *schedulingv1alpha3.CompositeDisruptionMode { + return oldObj.DisruptionMode + }) + errs = append(errs, fn(fldPath.Child("disruptionMode"), obj.DisruptionMode, oldVal, oldObj != nil)...) + } + { // field schedulingv1alpha3.CompositePodGroupSpec.PriorityClassName fn := func( fldPath *field.Path, @@ -523,38 +676,45 @@ func Validate_CompositePodGroupSpec( errs = append(errs, fn(fldPath.Child("priority"), obj.Priority, oldVal, oldObj != nil)...) } - { // field schedulingv1alpha3.CompositePodGroupSpec.SchedulingConstraints + { // field schedulingv1alpha3.CompositePodGroupSpec.PreemptionPolicy fn := func( fldPath *field.Path, - obj, oldObj *schedulingv1alpha3.CompositePodGroupSchedulingConstraints, + obj, oldObj *schedulingv1alpha3.PreemptionPolicy, oldValueCorrelated bool) (errs field.ErrorList) { // don't revalidate unchanged data if oldValueCorrelated && op.Type == operation.Update { - if equality.Semantic.DeepEqual(obj, oldObj) { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { return nil } } // call field-attached validations earlyReturn := false - if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", false, validate.ForbiddenPointer).MarkShortCircuit(); len(e) != 0 { errs = append(errs, e...) earlyReturn = true } - if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", false, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", true, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) earlyReturn = true } if earlyReturn { return // do not proceed } // call the type's validation function - errs = append(errs, Validate_CompositePodGroupSchedulingConstraints(ctx, op, fldPath, obj, oldObj)...) + errs = append(errs, Validate_PreemptionPolicy(ctx, op, fldPath, obj, oldObj)...) return } oldVal := safe.Field(oldObj, - func(oldObj *schedulingv1alpha3.CompositePodGroupSpec) *schedulingv1alpha3.CompositePodGroupSchedulingConstraints { - return oldObj.SchedulingConstraints + func(oldObj *schedulingv1alpha3.CompositePodGroupSpec) *schedulingv1alpha3.PreemptionPolicy { + return oldObj.PreemptionPolicy }) - errs = append(errs, fn(fldPath.Child("schedulingConstraints"), obj.SchedulingConstraints, oldVal, oldObj != nil)...) + errs = append(errs, fn(fldPath.Child("preemptionPolicy"), obj.PreemptionPolicy, oldVal, oldObj != nil)...) } return errs @@ -667,6 +827,74 @@ func Validate_CompositePodGroupTemplate( errs = append(errs, fn(fldPath.Child("schedulingPolicy"), &obj.SchedulingPolicy, oldVal, oldObj != nil)...) } + { // field schedulingv1alpha3.CompositePodGroupTemplate.SchedulingConstraints + fn := func( + fldPath *field.Path, + obj, oldObj *schedulingv1alpha3.CompositePodGroupSchedulingConstraints, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_CompositePodGroupSchedulingConstraints(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *schedulingv1alpha3.CompositePodGroupTemplate) *schedulingv1alpha3.CompositePodGroupSchedulingConstraints { + return oldObj.SchedulingConstraints + }) + errs = append(errs, fn(fldPath.Child("schedulingConstraints"), obj.SchedulingConstraints, oldVal, oldObj != nil)...) + } + + { // field schedulingv1alpha3.CompositePodGroupTemplate.DisruptionMode + fn := func( + fldPath *field.Path, + obj, oldObj *schedulingv1alpha3.CompositeDisruptionMode, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_CompositeDisruptionMode(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *schedulingv1alpha3.CompositePodGroupTemplate) *schedulingv1alpha3.CompositeDisruptionMode { + return oldObj.DisruptionMode + }) + errs = append(errs, fn(fldPath.Child("disruptionMode"), obj.DisruptionMode, oldVal, oldObj != nil)...) + } + { // field schedulingv1alpha3.CompositePodGroupTemplate.PriorityClassName fn := func( fldPath *field.Path, @@ -737,6 +965,47 @@ func Validate_CompositePodGroupTemplate( errs = append(errs, fn(fldPath.Child("priority"), obj.Priority, oldVal, oldObj != nil)...) } + { // field schedulingv1alpha3.CompositePodGroupTemplate.PreemptionPolicy + fn := func( + fldPath *field.Path, + obj, oldObj *schedulingv1alpha3.PreemptionPolicy, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", false, validate.ForbiddenPointer).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", false, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", true, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_PreemptionPolicy(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *schedulingv1alpha3.CompositePodGroupTemplate) *schedulingv1alpha3.PreemptionPolicy { + return oldObj.PreemptionPolicy + }) + errs = append(errs, fn(fldPath.Child("preemptionPolicy"), obj.PreemptionPolicy, oldVal, oldObj != nil)...) + } + { // field schedulingv1alpha3.CompositePodGroupTemplate.PodGroupTemplates fn := func( fldPath *field.Path, @@ -843,40 +1112,6 @@ func Validate_CompositePodGroupTemplate( errs = append(errs, fn(fldPath.Child("compositePodGroupTemplates"), obj.CompositePodGroupTemplates, oldVal, oldObj != nil)...) } - { // field schedulingv1alpha3.CompositePodGroupTemplate.SchedulingConstraints - fn := func( - fldPath *field.Path, - obj, oldObj *schedulingv1alpha3.CompositePodGroupSchedulingConstraints, - oldValueCorrelated bool) (errs field.ErrorList) { - // don't revalidate unchanged data - if oldValueCorrelated && op.Type == operation.Update { - if equality.Semantic.DeepEqual(obj, oldObj) { - return nil - } - } - // call field-attached validations - earlyReturn := false - if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { - errs = append(errs, e...) - earlyReturn = true - } - if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { - earlyReturn = true - } - if earlyReturn { - return // do not proceed - } - // call the type's validation function - errs = append(errs, Validate_CompositePodGroupSchedulingConstraints(ctx, op, fldPath, obj, oldObj)...) - return - } - oldVal := safe.Field(oldObj, - func(oldObj *schedulingv1alpha3.CompositePodGroupTemplate) *schedulingv1alpha3.CompositePodGroupSchedulingConstraints { - return oldObj.SchedulingConstraints - }) - errs = append(errs, fn(fldPath.Child("schedulingConstraints"), obj.SchedulingConstraints, oldVal, oldObj != nil)...) - } - return errs } diff --git a/pkg/apis/scheduling/v1beta1/zz_generated.conversion.go b/pkg/apis/scheduling/v1beta1/zz_generated.conversion.go index a896d46ae1c..c5938c0e458 100644 --- a/pkg/apis/scheduling/v1beta1/zz_generated.conversion.go +++ b/pkg/apis/scheduling/v1beta1/zz_generated.conversion.go @@ -39,6 +39,16 @@ func init() { // RegisterConversions adds conversion functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*schedulingv1beta1.AllCompositeDisruptionMode)(nil), (*scheduling.AllCompositeDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_AllCompositeDisruptionMode_To_scheduling_AllCompositeDisruptionMode(a.(*schedulingv1beta1.AllCompositeDisruptionMode), b.(*scheduling.AllCompositeDisruptionMode), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheduling.AllCompositeDisruptionMode)(nil), (*schedulingv1beta1.AllCompositeDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheduling_AllCompositeDisruptionMode_To_v1beta1_AllCompositeDisruptionMode(a.(*scheduling.AllCompositeDisruptionMode), b.(*schedulingv1beta1.AllCompositeDisruptionMode), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*schedulingv1beta1.AllDisruptionMode)(nil), (*scheduling.AllDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_AllDisruptionMode_To_scheduling_AllDisruptionMode(a.(*schedulingv1beta1.AllDisruptionMode), b.(*scheduling.AllDisruptionMode), scope) }); err != nil { @@ -69,6 +79,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*schedulingv1beta1.CompositeDisruptionMode)(nil), (*scheduling.CompositeDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_CompositeDisruptionMode_To_scheduling_CompositeDisruptionMode(a.(*schedulingv1beta1.CompositeDisruptionMode), b.(*scheduling.CompositeDisruptionMode), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheduling.CompositeDisruptionMode)(nil), (*schedulingv1beta1.CompositeDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheduling_CompositeDisruptionMode_To_v1beta1_CompositeDisruptionMode(a.(*scheduling.CompositeDisruptionMode), b.(*schedulingv1beta1.CompositeDisruptionMode), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*schedulingv1beta1.CompositeGangSchedulingPolicy)(nil), (*scheduling.CompositeGangSchedulingPolicy)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_CompositeGangSchedulingPolicy_To_scheduling_CompositeGangSchedulingPolicy(a.(*schedulingv1beta1.CompositeGangSchedulingPolicy), b.(*scheduling.CompositeGangSchedulingPolicy), scope) }); err != nil { @@ -239,6 +259,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*schedulingv1beta1.SingleCompositeDisruptionMode)(nil), (*scheduling.SingleCompositeDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SingleCompositeDisruptionMode_To_scheduling_SingleCompositeDisruptionMode(a.(*schedulingv1beta1.SingleCompositeDisruptionMode), b.(*scheduling.SingleCompositeDisruptionMode), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheduling.SingleCompositeDisruptionMode)(nil), (*schedulingv1beta1.SingleCompositeDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheduling_SingleCompositeDisruptionMode_To_v1beta1_SingleCompositeDisruptionMode(a.(*scheduling.SingleCompositeDisruptionMode), b.(*schedulingv1beta1.SingleCompositeDisruptionMode), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*schedulingv1beta1.SingleDisruptionMode)(nil), (*scheduling.SingleDisruptionMode)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_SingleDisruptionMode_To_scheduling_SingleDisruptionMode(a.(*schedulingv1beta1.SingleDisruptionMode), b.(*scheduling.SingleDisruptionMode), scope) }); err != nil { @@ -312,6 +342,26 @@ func RegisterConversions(s *runtime.Scheme) error { return nil } +func autoConvert_v1beta1_AllCompositeDisruptionMode_To_scheduling_AllCompositeDisruptionMode(in *schedulingv1beta1.AllCompositeDisruptionMode, out *scheduling.AllCompositeDisruptionMode, s conversion.Scope) error { + *out = *(*scheduling.AllCompositeDisruptionMode)(unsafe.Pointer(in)) + return nil +} + +// Convert_v1beta1_AllCompositeDisruptionMode_To_scheduling_AllCompositeDisruptionMode is an autogenerated conversion function. +func Convert_v1beta1_AllCompositeDisruptionMode_To_scheduling_AllCompositeDisruptionMode(in *schedulingv1beta1.AllCompositeDisruptionMode, out *scheduling.AllCompositeDisruptionMode, s conversion.Scope) error { + return autoConvert_v1beta1_AllCompositeDisruptionMode_To_scheduling_AllCompositeDisruptionMode(in, out, s) +} + +func autoConvert_scheduling_AllCompositeDisruptionMode_To_v1beta1_AllCompositeDisruptionMode(in *scheduling.AllCompositeDisruptionMode, out *schedulingv1beta1.AllCompositeDisruptionMode, s conversion.Scope) error { + *out = *(*schedulingv1beta1.AllCompositeDisruptionMode)(unsafe.Pointer(in)) + return nil +} + +// Convert_scheduling_AllCompositeDisruptionMode_To_v1beta1_AllCompositeDisruptionMode is an autogenerated conversion function. +func Convert_scheduling_AllCompositeDisruptionMode_To_v1beta1_AllCompositeDisruptionMode(in *scheduling.AllCompositeDisruptionMode, out *schedulingv1beta1.AllCompositeDisruptionMode, s conversion.Scope) error { + return autoConvert_scheduling_AllCompositeDisruptionMode_To_v1beta1_AllCompositeDisruptionMode(in, out, s) +} + func autoConvert_v1beta1_AllDisruptionMode_To_scheduling_AllDisruptionMode(in *schedulingv1beta1.AllDisruptionMode, out *scheduling.AllDisruptionMode, s conversion.Scope) error { *out = *(*scheduling.AllDisruptionMode)(unsafe.Pointer(in)) return nil @@ -372,6 +422,26 @@ func Convert_scheduling_CompositeBasicSchedulingPolicy_To_v1beta1_CompositeBasic return autoConvert_scheduling_CompositeBasicSchedulingPolicy_To_v1beta1_CompositeBasicSchedulingPolicy(in, out, s) } +func autoConvert_v1beta1_CompositeDisruptionMode_To_scheduling_CompositeDisruptionMode(in *schedulingv1beta1.CompositeDisruptionMode, out *scheduling.CompositeDisruptionMode, s conversion.Scope) error { + *out = *(*scheduling.CompositeDisruptionMode)(unsafe.Pointer(in)) + return nil +} + +// Convert_v1beta1_CompositeDisruptionMode_To_scheduling_CompositeDisruptionMode is an autogenerated conversion function. +func Convert_v1beta1_CompositeDisruptionMode_To_scheduling_CompositeDisruptionMode(in *schedulingv1beta1.CompositeDisruptionMode, out *scheduling.CompositeDisruptionMode, s conversion.Scope) error { + return autoConvert_v1beta1_CompositeDisruptionMode_To_scheduling_CompositeDisruptionMode(in, out, s) +} + +func autoConvert_scheduling_CompositeDisruptionMode_To_v1beta1_CompositeDisruptionMode(in *scheduling.CompositeDisruptionMode, out *schedulingv1beta1.CompositeDisruptionMode, s conversion.Scope) error { + *out = *(*schedulingv1beta1.CompositeDisruptionMode)(unsafe.Pointer(in)) + return nil +} + +// Convert_scheduling_CompositeDisruptionMode_To_v1beta1_CompositeDisruptionMode is an autogenerated conversion function. +func Convert_scheduling_CompositeDisruptionMode_To_v1beta1_CompositeDisruptionMode(in *scheduling.CompositeDisruptionMode, out *schedulingv1beta1.CompositeDisruptionMode, s conversion.Scope) error { + return autoConvert_scheduling_CompositeDisruptionMode_To_v1beta1_CompositeDisruptionMode(in, out, s) +} + func autoConvert_v1beta1_CompositeGangSchedulingPolicy_To_scheduling_CompositeGangSchedulingPolicy(in *schedulingv1beta1.CompositeGangSchedulingPolicy, out *scheduling.CompositeGangSchedulingPolicy, s conversion.Scope) error { *out = *(*scheduling.CompositeGangSchedulingPolicy)(unsafe.Pointer(in)) return nil @@ -736,6 +806,26 @@ func Convert_scheduling_PriorityClassList_To_v1beta1_PriorityClassList(in *sched return autoConvert_scheduling_PriorityClassList_To_v1beta1_PriorityClassList(in, out, s) } +func autoConvert_v1beta1_SingleCompositeDisruptionMode_To_scheduling_SingleCompositeDisruptionMode(in *schedulingv1beta1.SingleCompositeDisruptionMode, out *scheduling.SingleCompositeDisruptionMode, s conversion.Scope) error { + *out = *(*scheduling.SingleCompositeDisruptionMode)(unsafe.Pointer(in)) + return nil +} + +// Convert_v1beta1_SingleCompositeDisruptionMode_To_scheduling_SingleCompositeDisruptionMode is an autogenerated conversion function. +func Convert_v1beta1_SingleCompositeDisruptionMode_To_scheduling_SingleCompositeDisruptionMode(in *schedulingv1beta1.SingleCompositeDisruptionMode, out *scheduling.SingleCompositeDisruptionMode, s conversion.Scope) error { + return autoConvert_v1beta1_SingleCompositeDisruptionMode_To_scheduling_SingleCompositeDisruptionMode(in, out, s) +} + +func autoConvert_scheduling_SingleCompositeDisruptionMode_To_v1beta1_SingleCompositeDisruptionMode(in *scheduling.SingleCompositeDisruptionMode, out *schedulingv1beta1.SingleCompositeDisruptionMode, s conversion.Scope) error { + *out = *(*schedulingv1beta1.SingleCompositeDisruptionMode)(unsafe.Pointer(in)) + return nil +} + +// Convert_scheduling_SingleCompositeDisruptionMode_To_v1beta1_SingleCompositeDisruptionMode is an autogenerated conversion function. +func Convert_scheduling_SingleCompositeDisruptionMode_To_v1beta1_SingleCompositeDisruptionMode(in *scheduling.SingleCompositeDisruptionMode, out *schedulingv1beta1.SingleCompositeDisruptionMode, s conversion.Scope) error { + return autoConvert_scheduling_SingleCompositeDisruptionMode_To_v1beta1_SingleCompositeDisruptionMode(in, out, s) +} + func autoConvert_v1beta1_SingleDisruptionMode_To_scheduling_SingleDisruptionMode(in *schedulingv1beta1.SingleDisruptionMode, out *scheduling.SingleDisruptionMode, s conversion.Scope) error { *out = *(*scheduling.SingleDisruptionMode)(unsafe.Pointer(in)) return nil diff --git a/pkg/apis/scheduling/v1beta1/zz_generated.validations.go b/pkg/apis/scheduling/v1beta1/zz_generated.validations.go index 56600766945..69147414073 100644 --- a/pkg/apis/scheduling/v1beta1/zz_generated.validations.go +++ b/pkg/apis/scheduling/v1beta1/zz_generated.validations.go @@ -90,6 +90,89 @@ func RegisterValidations(scheme *runtime.Scheme) error { return nil } +var unionMembershipFor_k8s_io_api_scheduling_v1beta1_CompositeDisruptionMode_ = validate.NewUnionMembership(validate.NewUnionMember("single"), validate.NewUnionMember("all")) + +// Validate_CompositeDisruptionMode validates an instance of CompositeDisruptionMode according +// to declarative validation rules in the API schema. +func Validate_CompositeDisruptionMode( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *schedulingv1beta1.CompositeDisruptionMode) (errs field.ErrorList) { + + if e := validate.Union(ctx, op, fldPath, obj, oldObj, unionMembershipFor_k8s_io_api_scheduling_v1beta1_CompositeDisruptionMode_, + func(obj *schedulingv1beta1.CompositeDisruptionMode) bool { + if obj == nil { + return false + } + return obj.Single != nil + }, + func(obj *schedulingv1beta1.CompositeDisruptionMode) bool { + if obj == nil { + return false + } + return obj.All != nil + }); len(e) != 0 { + errs = append(errs, e...) + } + + { // field schedulingv1beta1.CompositeDisruptionMode.Single + fn := func( + fldPath *field.Path, + obj, oldObj *schedulingv1beta1.SingleCompositeDisruptionMode, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *schedulingv1beta1.CompositeDisruptionMode) *schedulingv1beta1.SingleCompositeDisruptionMode { + return oldObj.Single + }) + errs = append(errs, fn(fldPath.Child("single"), obj.Single, oldVal, oldObj != nil)...) + } + + { // field schedulingv1beta1.CompositeDisruptionMode.All + fn := func( + fldPath *field.Path, + obj, oldObj *schedulingv1beta1.AllCompositeDisruptionMode, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *schedulingv1beta1.CompositeDisruptionMode) *schedulingv1beta1.AllCompositeDisruptionMode { + return oldObj.All + }) + errs = append(errs, fn(fldPath.Child("all"), obj.All, oldVal, oldObj != nil)...) + } + + return errs +} + // Validate_CompositeGangSchedulingPolicy validates an instance of CompositeGangSchedulingPolicy according // to declarative validation rules in the API schema. func Validate_CompositeGangSchedulingPolicy( @@ -329,6 +412,74 @@ func Validate_CompositePodGroupTemplate( errs = append(errs, fn(fldPath.Child("schedulingPolicy"), &obj.SchedulingPolicy, oldVal, oldObj != nil)...) } + { // field schedulingv1beta1.CompositePodGroupTemplate.SchedulingConstraints + fn := func( + fldPath *field.Path, + obj, oldObj *schedulingv1beta1.CompositePodGroupSchedulingConstraints, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_CompositePodGroupSchedulingConstraints(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *schedulingv1beta1.CompositePodGroupTemplate) *schedulingv1beta1.CompositePodGroupSchedulingConstraints { + return oldObj.SchedulingConstraints + }) + errs = append(errs, fn(fldPath.Child("schedulingConstraints"), obj.SchedulingConstraints, oldVal, oldObj != nil)...) + } + + { // field schedulingv1beta1.CompositePodGroupTemplate.DisruptionMode + fn := func( + fldPath *field.Path, + obj, oldObj *schedulingv1beta1.CompositeDisruptionMode, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_CompositeDisruptionMode(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *schedulingv1beta1.CompositePodGroupTemplate) *schedulingv1beta1.CompositeDisruptionMode { + return oldObj.DisruptionMode + }) + errs = append(errs, fn(fldPath.Child("disruptionMode"), obj.DisruptionMode, oldVal, oldObj != nil)...) + } + { // field schedulingv1beta1.CompositePodGroupTemplate.PriorityClassName fn := func( fldPath *field.Path, @@ -399,6 +550,47 @@ func Validate_CompositePodGroupTemplate( errs = append(errs, fn(fldPath.Child("priority"), obj.Priority, oldVal, oldObj != nil)...) } + { // field schedulingv1beta1.CompositePodGroupTemplate.PreemptionPolicy + fn := func( + fldPath *field.Path, + obj, oldObj *schedulingv1beta1.PreemptionPolicy, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", false, validate.ForbiddenPointer).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", false, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", true, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_PreemptionPolicy(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *schedulingv1beta1.CompositePodGroupTemplate) *schedulingv1beta1.PreemptionPolicy { + return oldObj.PreemptionPolicy + }) + errs = append(errs, fn(fldPath.Child("preemptionPolicy"), obj.PreemptionPolicy, oldVal, oldObj != nil)...) + } + { // field schedulingv1beta1.CompositePodGroupTemplate.PodGroupTemplates fn := func( fldPath *field.Path, @@ -505,40 +697,6 @@ func Validate_CompositePodGroupTemplate( errs = append(errs, fn(fldPath.Child("compositePodGroupTemplates"), obj.CompositePodGroupTemplates, oldVal, oldObj != nil)...) } - { // field schedulingv1beta1.CompositePodGroupTemplate.SchedulingConstraints - fn := func( - fldPath *field.Path, - obj, oldObj *schedulingv1beta1.CompositePodGroupSchedulingConstraints, - oldValueCorrelated bool) (errs field.ErrorList) { - // don't revalidate unchanged data - if oldValueCorrelated && op.Type == operation.Update { - if equality.Semantic.DeepEqual(obj, oldObj) { - return nil - } - } - // call field-attached validations - earlyReturn := false - if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { - errs = append(errs, e...) - earlyReturn = true - } - if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { - earlyReturn = true - } - if earlyReturn { - return // do not proceed - } - // call the type's validation function - errs = append(errs, Validate_CompositePodGroupSchedulingConstraints(ctx, op, fldPath, obj, oldObj)...) - return - } - oldVal := safe.Field(oldObj, - func(oldObj *schedulingv1beta1.CompositePodGroupTemplate) *schedulingv1beta1.CompositePodGroupSchedulingConstraints { - return oldObj.SchedulingConstraints - }) - errs = append(errs, fn(fldPath.Child("schedulingConstraints"), obj.SchedulingConstraints, oldVal, oldObj != nil)...) - } - return errs } diff --git a/pkg/apis/scheduling/zz_generated.deepcopy.go b/pkg/apis/scheduling/zz_generated.deepcopy.go index e0fc1b726ca..e1f4ecf7d4a 100644 --- a/pkg/apis/scheduling/zz_generated.deepcopy.go +++ b/pkg/apis/scheduling/zz_generated.deepcopy.go @@ -27,6 +27,22 @@ import ( core "k8s.io/kubernetes/pkg/apis/core" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AllCompositeDisruptionMode) DeepCopyInto(out *AllCompositeDisruptionMode) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllCompositeDisruptionMode. +func (in *AllCompositeDisruptionMode) DeepCopy() *AllCompositeDisruptionMode { + if in == nil { + return nil + } + out := new(AllCompositeDisruptionMode) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AllDisruptionMode) DeepCopyInto(out *AllDisruptionMode) { *out = *in @@ -75,6 +91,32 @@ func (in *CompositeBasicSchedulingPolicy) DeepCopy() *CompositeBasicSchedulingPo return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CompositeDisruptionMode) DeepCopyInto(out *CompositeDisruptionMode) { + *out = *in + if in.Single != nil { + in, out := &in.Single, &out.Single + *out = new(SingleCompositeDisruptionMode) + **out = **in + } + if in.All != nil { + in, out := &in.All, &out.All + *out = new(AllCompositeDisruptionMode) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CompositeDisruptionMode. +func (in *CompositeDisruptionMode) DeepCopy() *CompositeDisruptionMode { + if in == nil { + return nil + } + out := new(CompositeDisruptionMode) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CompositeGangSchedulingPolicy) DeepCopyInto(out *CompositeGangSchedulingPolicy) { *out = *in @@ -213,15 +255,25 @@ func (in *CompositePodGroupSpec) DeepCopyInto(out *CompositePodGroupSpec) { **out = **in } in.SchedulingPolicy.DeepCopyInto(&out.SchedulingPolicy) + if in.SchedulingConstraints != nil { + in, out := &in.SchedulingConstraints, &out.SchedulingConstraints + *out = new(CompositePodGroupSchedulingConstraints) + (*in).DeepCopyInto(*out) + } + if in.DisruptionMode != nil { + in, out := &in.DisruptionMode, &out.DisruptionMode + *out = new(CompositeDisruptionMode) + (*in).DeepCopyInto(*out) + } if in.Priority != nil { in, out := &in.Priority, &out.Priority *out = new(int32) **out = **in } - if in.SchedulingConstraints != nil { - in, out := &in.SchedulingConstraints, &out.SchedulingConstraints - *out = new(CompositePodGroupSchedulingConstraints) - (*in).DeepCopyInto(*out) + if in.PreemptionPolicy != nil { + in, out := &in.PreemptionPolicy, &out.PreemptionPolicy + *out = new(PreemptionPolicy) + **out = **in } return } @@ -263,11 +315,26 @@ func (in *CompositePodGroupStatus) DeepCopy() *CompositePodGroupStatus { func (in *CompositePodGroupTemplate) DeepCopyInto(out *CompositePodGroupTemplate) { *out = *in in.SchedulingPolicy.DeepCopyInto(&out.SchedulingPolicy) + if in.SchedulingConstraints != nil { + in, out := &in.SchedulingConstraints, &out.SchedulingConstraints + *out = new(CompositePodGroupSchedulingConstraints) + (*in).DeepCopyInto(*out) + } + if in.DisruptionMode != nil { + in, out := &in.DisruptionMode, &out.DisruptionMode + *out = new(CompositeDisruptionMode) + (*in).DeepCopyInto(*out) + } if in.Priority != nil { in, out := &in.Priority, &out.Priority *out = new(int32) **out = **in } + if in.PreemptionPolicy != nil { + in, out := &in.PreemptionPolicy, &out.PreemptionPolicy + *out = new(PreemptionPolicy) + **out = **in + } if in.PodGroupTemplates != nil { in, out := &in.PodGroupTemplates, &out.PodGroupTemplates *out = make([]PodGroupTemplate, len(*in)) @@ -282,11 +349,6 @@ func (in *CompositePodGroupTemplate) DeepCopyInto(out *CompositePodGroupTemplate (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.SchedulingConstraints != nil { - in, out := &in.SchedulingConstraints, &out.SchedulingConstraints - *out = new(CompositePodGroupSchedulingConstraints) - (*in).DeepCopyInto(*out) - } return } @@ -689,6 +751,22 @@ func (in *PriorityClassList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SingleCompositeDisruptionMode) DeepCopyInto(out *SingleCompositeDisruptionMode) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SingleCompositeDisruptionMode. +func (in *SingleCompositeDisruptionMode) DeepCopy() *SingleCompositeDisruptionMode { + if in == nil { + return nil + } + out := new(SingleCompositeDisruptionMode) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SingleDisruptionMode) DeepCopyInto(out *SingleDisruptionMode) { *out = *in diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 4859b654948..6f7ecf28d3c 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -1157,9 +1157,11 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA resourcev1beta2.ResourceSliceSpec{}.OpenAPIModelName(): schema_k8sio_api_resource_v1beta2_ResourceSliceSpec(ref), schedulingv1.PriorityClass{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1_PriorityClass(ref), schedulingv1.PriorityClassList{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1_PriorityClassList(ref), + schedulingv1alpha3.AllCompositeDisruptionMode{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_AllCompositeDisruptionMode(ref), schedulingv1alpha3.AllDisruptionMode{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_AllDisruptionMode(ref), schedulingv1alpha3.BasicSchedulingPolicy{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_BasicSchedulingPolicy(ref), schedulingv1alpha3.CompositeBasicSchedulingPolicy{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_CompositeBasicSchedulingPolicy(ref), + schedulingv1alpha3.CompositeDisruptionMode{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_CompositeDisruptionMode(ref), schedulingv1alpha3.CompositeGangSchedulingPolicy{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_CompositeGangSchedulingPolicy(ref), schedulingv1alpha3.CompositePodGroup{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_CompositePodGroup(ref), schedulingv1alpha3.CompositePodGroupList{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_CompositePodGroupList(ref), @@ -1179,6 +1181,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA schedulingv1alpha3.PodGroupSpec{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_PodGroupSpec(ref), schedulingv1alpha3.PodGroupStatus{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_PodGroupStatus(ref), schedulingv1alpha3.PodGroupTemplate{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_PodGroupTemplate(ref), + schedulingv1alpha3.SingleCompositeDisruptionMode{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_SingleCompositeDisruptionMode(ref), schedulingv1alpha3.SingleDisruptionMode{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_SingleDisruptionMode(ref), schedulingv1alpha3.TopologyConstraint{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_TopologyConstraint(ref), schedulingv1alpha3.TypedLocalObjectReference{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_TypedLocalObjectReference(ref), @@ -1194,9 +1197,11 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA schedulingv1alpha3.WorkloadPodGroupSingleDisruptionMode{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_WorkloadPodGroupSingleDisruptionMode(ref), schedulingv1alpha3.WorkloadReference{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_WorkloadReference(ref), schedulingv1alpha3.WorkloadSpec{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1alpha3_WorkloadSpec(ref), + schedulingv1beta1.AllCompositeDisruptionMode{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_AllCompositeDisruptionMode(ref), schedulingv1beta1.AllDisruptionMode{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_AllDisruptionMode(ref), schedulingv1beta1.BasicSchedulingPolicy{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_BasicSchedulingPolicy(ref), schedulingv1beta1.CompositeBasicSchedulingPolicy{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_CompositeBasicSchedulingPolicy(ref), + schedulingv1beta1.CompositeDisruptionMode{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_CompositeDisruptionMode(ref), schedulingv1beta1.CompositeGangSchedulingPolicy{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_CompositeGangSchedulingPolicy(ref), schedulingv1beta1.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_CompositePodGroupSchedulingConstraints(ref), schedulingv1beta1.CompositePodGroupSchedulingPolicy{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_CompositePodGroupSchedulingPolicy(ref), @@ -1214,6 +1219,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA schedulingv1beta1.PodGroupTemplate{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_PodGroupTemplate(ref), schedulingv1beta1.PriorityClass{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_PriorityClass(ref), schedulingv1beta1.PriorityClassList{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_PriorityClassList(ref), + schedulingv1beta1.SingleCompositeDisruptionMode{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_SingleCompositeDisruptionMode(ref), schedulingv1beta1.SingleDisruptionMode{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_SingleDisruptionMode(ref), schedulingv1beta1.TopologyConstraint{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_TopologyConstraint(ref), schedulingv1beta1.TypedLocalObjectReference{}.OpenAPIModelName(): schema_k8sio_api_scheduling_v1beta1_TypedLocalObjectReference(ref), @@ -54776,6 +54782,17 @@ func schema_k8sio_api_scheduling_v1_PriorityClassList(ref common.ReferenceCallba } } +func schema_k8sio_api_scheduling_v1alpha3_AllCompositeDisruptionMode(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "AllCompositeDisruptionMode means that children of a CompositePodGroup can only be disrupted or preempted together.", + Type: []string{"object"}, + }, + }, + } +} + func schema_k8sio_api_scheduling_v1alpha3_AllDisruptionMode(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -54809,6 +54826,45 @@ func schema_k8sio_api_scheduling_v1alpha3_CompositeBasicSchedulingPolicy(ref com } } +func schema_k8sio_api_scheduling_v1alpha3_CompositeDisruptionMode(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. Exactly one mode must be set.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "single": { + SchemaProps: spec.SchemaProps{ + Description: "single specifies that children groups can be disrupted independently from each other.", + Ref: ref(schedulingv1alpha3.SingleCompositeDisruptionMode{}.OpenAPIModelName()), + }, + }, + "all": { + SchemaProps: spec.SchemaProps{ + Description: "all specifies that all children groups can only be disrupted together.", + Ref: ref(schedulingv1alpha3.AllCompositeDisruptionMode{}.OpenAPIModelName()), + }, + }, + }, + }, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-unions": []interface{}{ + map[string]interface{}{ + "fields-to-discriminateBy": map[string]interface{}{ + "all": "All", + "single": "Single", + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + schedulingv1alpha3.AllCompositeDisruptionMode{}.OpenAPIModelName(), schedulingv1alpha3.SingleCompositeDisruptionMode{}.OpenAPIModelName()}, + } +} + func schema_k8sio_api_scheduling_v1alpha3_CompositeGangSchedulingPolicy(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -55031,6 +55087,19 @@ func schema_k8sio_api_scheduling_v1alpha3_CompositePodGroupSpec(ref common.Refer Ref: ref(schedulingv1alpha3.CompositePodGroupSchedulingPolicy{}.OpenAPIModelName()), }, }, + "schedulingConstraints": { + SchemaProps: spec.SchemaProps{ + Description: "schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroup. Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. This field is immutable.", + Ref: ref(schedulingv1alpha3.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName()), + }, + }, + "disruptionMode": { + SchemaProps: spec.SchemaProps{ + Description: "disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. One of Single, All. Defaults to Single if unset. This field is immutable.", + Default: map[string]interface{}{"single": map[string]interface{}{}}, + Ref: ref(schedulingv1alpha3.CompositeDisruptionMode{}.OpenAPIModelName()), + }, + }, "priorityClassName": { SchemaProps: spec.SchemaProps{ Description: "priorityClassName defines the priority that should be considered when scheduling this CompositePodGroup. Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. If left unspecified, it is validated and resolved similarly to the PriorityClassName field in Pods (i.e. if no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, the composite pod group's priority will be zero). This field is immutable.", @@ -55045,10 +55114,12 @@ func schema_k8sio_api_scheduling_v1alpha3_CompositePodGroupSpec(ref common.Refer Format: "int32", }, }, - "schedulingConstraints": { + "preemptionPolicy": { SchemaProps: spec.SchemaProps{ - Description: "schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroup. Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. This field is immutable.", - Ref: ref(schedulingv1alpha3.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName()), + Description: "preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. When Priority Admission Controller is enabled, it populates this field from PriorityClassName, and defaults to PreemptLowerPriority if value is unset in PriorityClass. This field is immutable. This field is available only when the PodGroupPreemptionPolicy feature gate is enabled.\n\n\nPossible enum values:\n - `\"Never\"` means that pod never preempts other pods with lower priority.\n - `\"PreemptLowerPriority\"` means that pod can preempt other pods with lower priority.", + Type: []string{"string"}, + Format: "", + Enum: []interface{}{"Never", "PreemptLowerPriority"}, }, }, }, @@ -55056,7 +55127,7 @@ func schema_k8sio_api_scheduling_v1alpha3_CompositePodGroupSpec(ref common.Refer }, }, Dependencies: []string{ - schedulingv1alpha3.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName(), schedulingv1alpha3.CompositePodGroupSchedulingPolicy{}.OpenAPIModelName(), schedulingv1alpha3.WorkloadReference{}.OpenAPIModelName()}, + schedulingv1alpha3.CompositeDisruptionMode{}.OpenAPIModelName(), schedulingv1alpha3.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName(), schedulingv1alpha3.CompositePodGroupSchedulingPolicy{}.OpenAPIModelName(), schedulingv1alpha3.WorkloadReference{}.OpenAPIModelName()}, } } @@ -55120,6 +55191,18 @@ func schema_k8sio_api_scheduling_v1alpha3_CompositePodGroupTemplate(ref common.R Ref: ref(schedulingv1alpha3.CompositePodGroupSchedulingPolicy{}.OpenAPIModelName()), }, }, + "schedulingConstraints": { + SchemaProps: spec.SchemaProps{ + Description: "schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. This field is immutable.", + Ref: ref(schedulingv1alpha3.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName()), + }, + }, + "disruptionMode": { + SchemaProps: spec.SchemaProps{ + Description: "disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. One of Single, All. This field is immutable.", + Ref: ref(schedulingv1alpha3.CompositeDisruptionMode{}.OpenAPIModelName()), + }, + }, "priorityClassName": { SchemaProps: spec.SchemaProps{ Description: "priorityClassName indicates the priority that should be considered when scheduling a composite pod group created from this template. If no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, composite pod groups created from this template will have the priority set to zero. This field is immutable.", @@ -55134,6 +55217,14 @@ func schema_k8sio_api_scheduling_v1alpha3_CompositePodGroupTemplate(ref common.R Format: "int32", }, }, + "preemptionPolicy": { + SchemaProps: spec.SchemaProps{ + Description: "preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. One of Never, PreemptLowerPriority. This field is immutable. This field is available only when the PodGroupPreemptionPolicy feature gate is enabled.\n\n\nPossible enum values:\n - `\"Never\"` means that pod never preempts other pods with lower priority.\n - `\"PreemptLowerPriority\"` means that pod can preempt other pods with lower priority.", + Type: []string{"string"}, + Format: "", + Enum: []interface{}{"Never", "PreemptLowerPriority"}, + }, + }, "podGroupTemplates": { VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ @@ -55176,18 +55267,12 @@ func schema_k8sio_api_scheduling_v1alpha3_CompositePodGroupTemplate(ref common.R }, }, }, - "schedulingConstraints": { - SchemaProps: spec.SchemaProps{ - Description: "schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. This field is immutable.", - Ref: ref(schedulingv1alpha3.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName()), - }, - }, }, Required: []string{"name", "schedulingPolicy"}, }, }, Dependencies: []string{ - schedulingv1alpha3.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName(), schedulingv1alpha3.CompositePodGroupSchedulingPolicy{}.OpenAPIModelName(), schedulingv1alpha3.CompositePodGroupTemplate{}.OpenAPIModelName(), schedulingv1alpha3.PodGroupTemplate{}.OpenAPIModelName()}, + schedulingv1alpha3.CompositeDisruptionMode{}.OpenAPIModelName(), schedulingv1alpha3.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName(), schedulingv1alpha3.CompositePodGroupSchedulingPolicy{}.OpenAPIModelName(), schedulingv1alpha3.CompositePodGroupTemplate{}.OpenAPIModelName(), schedulingv1alpha3.PodGroupTemplate{}.OpenAPIModelName()}, } } @@ -55733,6 +55818,17 @@ func schema_k8sio_api_scheduling_v1alpha3_PodGroupTemplate(ref common.ReferenceC } } +func schema_k8sio_api_scheduling_v1alpha3_SingleCompositeDisruptionMode(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "SingleCompositeDisruptionMode means that individual children of a CompositePodGroup can be disrupted or preempted independently.", + Type: []string{"object"}, + }, + }, + } +} + func schema_k8sio_api_scheduling_v1alpha3_SingleDisruptionMode(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -56190,6 +56286,17 @@ func schema_k8sio_api_scheduling_v1alpha3_WorkloadSpec(ref common.ReferenceCallb } } +func schema_k8sio_api_scheduling_v1beta1_AllCompositeDisruptionMode(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "AllCompositeDisruptionMode means that children of a CompositePodGroup can only be disrupted or preempted together.", + Type: []string{"object"}, + }, + }, + } +} + func schema_k8sio_api_scheduling_v1beta1_AllDisruptionMode(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -56223,6 +56330,45 @@ func schema_k8sio_api_scheduling_v1beta1_CompositeBasicSchedulingPolicy(ref comm } } +func schema_k8sio_api_scheduling_v1beta1_CompositeDisruptionMode(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. Exactly one mode must be set.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "single": { + SchemaProps: spec.SchemaProps{ + Description: "single specifies that children groups can be disrupted independently from each other.", + Ref: ref(schedulingv1beta1.SingleCompositeDisruptionMode{}.OpenAPIModelName()), + }, + }, + "all": { + SchemaProps: spec.SchemaProps{ + Description: "all specifies that all children groups can only be disrupted together.", + Ref: ref(schedulingv1beta1.AllCompositeDisruptionMode{}.OpenAPIModelName()), + }, + }, + }, + }, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-unions": []interface{}{ + map[string]interface{}{ + "fields-to-discriminateBy": map[string]interface{}{ + "all": "All", + "single": "Single", + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + schedulingv1beta1.AllCompositeDisruptionMode{}.OpenAPIModelName(), schedulingv1beta1.SingleCompositeDisruptionMode{}.OpenAPIModelName()}, + } +} + func schema_k8sio_api_scheduling_v1beta1_CompositeGangSchedulingPolicy(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -56339,6 +56485,18 @@ func schema_k8sio_api_scheduling_v1beta1_CompositePodGroupTemplate(ref common.Re Ref: ref(schedulingv1beta1.CompositePodGroupSchedulingPolicy{}.OpenAPIModelName()), }, }, + "schedulingConstraints": { + SchemaProps: spec.SchemaProps{ + Description: "schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. This field is immutable.", + Ref: ref(schedulingv1beta1.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName()), + }, + }, + "disruptionMode": { + SchemaProps: spec.SchemaProps{ + Description: "disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. One of Single, All. This field is immutable.", + Ref: ref(schedulingv1beta1.CompositeDisruptionMode{}.OpenAPIModelName()), + }, + }, "priorityClassName": { SchemaProps: spec.SchemaProps{ Description: "priorityClassName indicates the priority that should be considered when scheduling a composite pod group created from this template. If no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, composite pod groups created from this template will have the priority set to zero. This field is immutable.", @@ -56353,6 +56511,14 @@ func schema_k8sio_api_scheduling_v1beta1_CompositePodGroupTemplate(ref common.Re Format: "int32", }, }, + "preemptionPolicy": { + SchemaProps: spec.SchemaProps{ + Description: "preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. One of Never, PreemptLowerPriority. This field is immutable. This field is available only when the PodGroupPreemptionPolicy feature gate is enabled.\n\n\nPossible enum values:\n - `\"Never\"` means that pod never preempts other pods with lower priority.\n - `\"PreemptLowerPriority\"` means that pod can preempt other pods with lower priority.", + Type: []string{"string"}, + Format: "", + Enum: []interface{}{"Never", "PreemptLowerPriority"}, + }, + }, "podGroupTemplates": { VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ @@ -56395,18 +56561,12 @@ func schema_k8sio_api_scheduling_v1beta1_CompositePodGroupTemplate(ref common.Re }, }, }, - "schedulingConstraints": { - SchemaProps: spec.SchemaProps{ - Description: "schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. This field is immutable.", - Ref: ref(schedulingv1beta1.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName()), - }, - }, }, Required: []string{"name", "schedulingPolicy"}, }, }, Dependencies: []string{ - schedulingv1beta1.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName(), schedulingv1beta1.CompositePodGroupSchedulingPolicy{}.OpenAPIModelName(), schedulingv1beta1.CompositePodGroupTemplate{}.OpenAPIModelName(), schedulingv1beta1.PodGroupTemplate{}.OpenAPIModelName()}, + schedulingv1beta1.CompositeDisruptionMode{}.OpenAPIModelName(), schedulingv1beta1.CompositePodGroupSchedulingConstraints{}.OpenAPIModelName(), schedulingv1beta1.CompositePodGroupSchedulingPolicy{}.OpenAPIModelName(), schedulingv1beta1.CompositePodGroupTemplate{}.OpenAPIModelName(), schedulingv1beta1.PodGroupTemplate{}.OpenAPIModelName()}, } } @@ -57068,6 +57228,17 @@ func schema_k8sio_api_scheduling_v1beta1_PriorityClassList(ref common.ReferenceC } } +func schema_k8sio_api_scheduling_v1beta1_SingleCompositeDisruptionMode(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "SingleCompositeDisruptionMode means that individual children of a CompositePodGroup can be disrupted or preempted independently.", + Type: []string{"object"}, + }, + }, + } +} + func schema_k8sio_api_scheduling_v1beta1_SingleDisruptionMode(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/registry/scheduling/compositepodgroup/strategy.go b/pkg/registry/scheduling/compositepodgroup/strategy.go index d796ad776b8..19f7cf535a1 100644 --- a/pkg/registry/scheduling/compositepodgroup/strategy.go +++ b/pkg/registry/scheduling/compositepodgroup/strategy.go @@ -62,6 +62,7 @@ func (*compositePodGroupStrategy) PrepareForCreate(ctx context.Context, obj runt cpg := obj.(*scheduling.CompositePodGroup) // Status must not be set by user on create. cpg.Status = scheduling.CompositePodGroupStatus{} + dropDisabledCompositePodGroupFields(cpg, nil) } func (*compositePodGroupStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { @@ -73,7 +74,8 @@ func (*compositePodGroupStrategy) Validate(ctx context.Context, obj runtime.Obje // mapped to whether each is enabled. func (*compositePodGroupStrategy) DeclarativeValidationConfig(ctx context.Context, obj, oldObj runtime.Object) rest.DeclarativeValidationConfig { return rest.DeclarativeValidationConfig{Options: map[string]bool{ - string(features.CompositePodGroup): utilfeature.DefaultFeatureGate.Enabled(features.CompositePodGroup), + string(features.CompositePodGroup): utilfeature.DefaultFeatureGate.Enabled(features.CompositePodGroup), + string(features.PodGroupPreemptionPolicy): utilfeature.DefaultFeatureGate.Enabled(features.PodGroupPreemptionPolicy), }} } @@ -91,6 +93,7 @@ func (*compositePodGroupStrategy) PrepareForUpdate(ctx context.Context, obj, old newCPG := obj.(*scheduling.CompositePodGroup) oldCPG := old.(*scheduling.CompositePodGroup) newCPG.Status = oldCPG.Status + dropDisabledCompositePodGroupFields(newCPG, oldCPG) } func (*compositePodGroupStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { @@ -141,3 +144,33 @@ func (r *compositePodGroupStatusStrategy) ValidateUpdate(ctx context.Context, ob func (*compositePodGroupStatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { return nil } + +// dropDisabledCompositePodGroupFields removes fields which are covered by a feature gate. +func dropDisabledCompositePodGroupFields(newCPG, oldCPG *scheduling.CompositePodGroup) { + var newCPGSpec, oldCPGSpec *scheduling.CompositePodGroupSpec + if newCPG != nil { + newCPGSpec = &newCPG.Spec + } + if oldCPG != nil { + oldCPGSpec = &oldCPG.Spec + } + dropDisabledCompositePodGroupSpecFields(newCPGSpec, oldCPGSpec) +} + +func dropDisabledCompositePodGroupSpecFields(newCPGSpec, oldCPGSpec *scheduling.CompositePodGroupSpec) { + dropDisabledPreemptionPolicyField(newCPGSpec, oldCPGSpec) +} + +// dropDisabledPreemptionPolicyField removes the PreemptionPolicy field unless it is +// already used in the old CompositePodGroup spec. +func dropDisabledPreemptionPolicyField(newCPGSpec, oldCPGSpec *scheduling.CompositePodGroupSpec) { + if utilfeature.DefaultFeatureGate.Enabled(features.PodGroupPreemptionPolicy) || preemptionPolicyInUse(oldCPGSpec) { + // No need to drop anything. + return + } + newCPGSpec.PreemptionPolicy = nil +} + +func preemptionPolicyInUse(cpgSpec *scheduling.CompositePodGroupSpec) bool { + return cpgSpec != nil && cpgSpec.PreemptionPolicy != nil +} diff --git a/pkg/registry/scheduling/compositepodgroup/strategy_test.go b/pkg/registry/scheduling/compositepodgroup/strategy_test.go index c3ca4d2880a..c690a22b3a1 100644 --- a/pkg/registry/scheduling/compositepodgroup/strategy_test.go +++ b/pkg/registry/scheduling/compositepodgroup/strategy_test.go @@ -50,15 +50,21 @@ var ( MinGroupCount: 5, }, }, + DisruptionMode: &scheduling.CompositeDisruptionMode{ + Single: &scheduling.SingleCompositeDisruptionMode{}, + }, }, } - fieldImmutableError = "field is immutable" - minCountError = "must be greater than or equal to 1" - subdomainNameError = "lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters" - maximumError = "must be less than or equal to" - oneOfError = "must specify one of: `basic`, `gang`" - multipleFieldsSetError = "must specify exactly one of: `basic`, `gang`" + fieldImmutableError = "field is immutable" + minCountError = "must be greater than or equal to 1" + subdomainNameError = "lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters" + maximumError = "must be less than or equal to" + oneOfError = "must specify one of: `basic`, `gang`" + multipleSchedulingPoliciesError = "must specify exactly one of: `basic`, `gang`" + multipleDisruptionModesError = "must specify exactly one of: `single`, `all`" + supportedPoliciesError = `supported values: "Never", "PreemptLowerPriority"` + forbiddenError = "Forbidden" ) func compositePodGroupWithSchedulingConstraints(keys ...string) *scheduling.CompositePodGroup { @@ -73,6 +79,29 @@ func compositePodGroupWithSchedulingConstraints(keys ...string) *scheduling.Comp return result } +func cpgWithDisruptionModeAll() *scheduling.CompositePodGroup { + cpg := cpg.DeepCopy() + cpg.Spec.DisruptionMode = &scheduling.CompositeDisruptionMode{ + All: &scheduling.AllCompositeDisruptionMode{}, + } + return cpg +} + +func cpgWithDisruptionModeBoth() *scheduling.CompositePodGroup { + cpg := cpg.DeepCopy() + cpg.Spec.DisruptionMode = &scheduling.CompositeDisruptionMode{ + Single: &scheduling.SingleCompositeDisruptionMode{}, + All: &scheduling.AllCompositeDisruptionMode{}, + } + return cpg +} + +func cpgWithPreemptionPolicy(policy scheduling.PreemptionPolicy) *scheduling.CompositePodGroup { + cpg := cpg.DeepCopy() + cpg.Spec.PreemptionPolicy = &policy + return cpg +} + func TestStrategy(t *testing.T) { strategy := NewStrategy() if !strategy.NamespaceScoped() { @@ -96,9 +125,10 @@ func TestStrategyCreate(t *testing.T) { ctx := ctxWithRequestInfo() testCases := map[string]struct { - obj *scheduling.CompositePodGroup - expectObj *scheduling.CompositePodGroup - expectValidationError string + obj *scheduling.CompositePodGroup + expectObj *scheduling.CompositePodGroup + enablePodGroupPreemptionPolicy bool + expectValidationError string }{ "simple": { obj: cpg, @@ -126,7 +156,7 @@ func TestStrategyCreate(t *testing.T) { c.Spec.SchedulingPolicy.Basic = &scheduling.CompositeBasicSchedulingPolicy{} return c }(), - expectValidationError: multipleFieldsSetError, + expectValidationError: multipleSchedulingPoliciesError, }, "validation error - neither basic nor gang specified": { obj: func() *scheduling.CompositePodGroup { @@ -192,6 +222,37 @@ func TestStrategyCreate(t *testing.T) { obj: compositePodGroupWithSchedulingConstraints("foo-"), expectValidationError: "Invalid value: \"foo-\"", }, + "disruption mode all": { + obj: cpgWithDisruptionModeAll(), + expectObj: cpgWithDisruptionModeAll(), + }, + "both disruption modes set": { + obj: cpgWithDisruptionModeBoth(), + expectValidationError: multipleDisruptionModesError, + }, + "podgroup preemptionPolicy disabled - drop preemptionPolicy": { + obj: cpgWithPreemptionPolicy(scheduling.PreemptNever), + expectObj: cpg, + }, + "podgroup preemptionPolicy disabled - drop invalid preemptionPolicy": { + obj: cpgWithPreemptionPolicy(scheduling.PreemptionPolicy("Invalid")), + expectObj: cpg, + }, + "podgroup preemptionPolicy enabled - preserve preemptionPolicy (Never)": { + obj: cpgWithPreemptionPolicy(scheduling.PreemptNever), + expectObj: cpgWithPreemptionPolicy(scheduling.PreemptNever), + enablePodGroupPreemptionPolicy: true, + }, + "podgroup preemptionPolicy enabled - preserve preemptionPolicy (PreemptLowerPriority)": { + obj: cpgWithPreemptionPolicy(scheduling.PreemptLowerPriority), + expectObj: cpgWithPreemptionPolicy(scheduling.PreemptLowerPriority), + enablePodGroupPreemptionPolicy: true, + }, + "podgroup preemptionPolicy enabled - invalid preemptionPolicy": { + obj: cpgWithPreemptionPolicy(scheduling.PreemptionPolicy("Invalid")), + enablePodGroupPreemptionPolicy: true, + expectValidationError: supportedPoliciesError, + }, } for name, tc := range testCases { @@ -200,6 +261,7 @@ func TestStrategyCreate(t *testing.T) { features.GenericWorkload: true, features.CompositePodGroup: true, features.TopologyAwareWorkloadScheduling: true, + features.PodGroupPreemptionPolicy: tc.enablePodGroupPreemptionPolicy, }) newCpg := tc.obj.DeepCopy() @@ -238,9 +300,10 @@ func TestStrategyCreate(t *testing.T) { func TestStrategyUpdate(t *testing.T) { ctx := ctxWithRequestInfo() testCases := map[string]struct { - oldObj *scheduling.CompositePodGroup - newObj *scheduling.CompositePodGroup - expectValidationError string + oldObj *scheduling.CompositePodGroup + newObj *scheduling.CompositePodGroup + enablePodGroupPreemptionPolicy bool + expectValidationErrors []string }{ "no changes": { oldObj: cpg, @@ -253,7 +316,7 @@ func TestStrategyUpdate(t *testing.T) { newCpg.Name += "bar" return newCpg }(), - expectValidationError: fieldImmutableError, + expectValidationErrors: []string{fieldImmutableError}, }, "updating workload ref not allowed": { oldObj: cpg, @@ -265,7 +328,7 @@ func TestStrategyUpdate(t *testing.T) { } return newCpg }(), - expectValidationError: fieldImmutableError, + expectValidationErrors: []string{fieldImmutableError}, }, "changing parentCompositePodGroupName from nil not allowed": { oldObj: cpg, @@ -275,7 +338,7 @@ func TestStrategyUpdate(t *testing.T) { newCpg.Spec.ParentCompositePodGroupName = &parent return newCpg }(), - expectValidationError: fieldImmutableError, + expectValidationErrors: []string{fieldImmutableError}, }, "changing parentCompositePodGroupName from non-nil not allowed": { oldObj: func() *scheduling.CompositePodGroup { @@ -290,7 +353,7 @@ func TestStrategyUpdate(t *testing.T) { newCpg.Spec.ParentCompositePodGroupName = &parent return newCpg }(), - expectValidationError: fieldImmutableError, + expectValidationErrors: []string{fieldImmutableError}, }, "changing min group count in gang scheduling policy not allowed": { oldObj: cpg, @@ -299,7 +362,7 @@ func TestStrategyUpdate(t *testing.T) { newCpg.Spec.SchedulingPolicy.Gang.MinGroupCount = 4 return newCpg }(), - expectValidationError: fieldImmutableError, + expectValidationErrors: []string{fieldImmutableError}, }, "changing scheduling policy not allowed": { oldObj: cpg, @@ -310,7 +373,12 @@ func TestStrategyUpdate(t *testing.T) { } return newCpg }(), - expectValidationError: fieldImmutableError, + expectValidationErrors: []string{fieldImmutableError}, + }, + "changing disruption mode not allowed": { + oldObj: cpg, + newObj: cpgWithDisruptionModeAll(), + expectValidationErrors: []string{fieldImmutableError}, }, "priority class name update": { oldObj: cpg, @@ -319,7 +387,7 @@ func TestStrategyUpdate(t *testing.T) { cpg.Spec.PriorityClassName = "high-priority" return cpg }(), - expectValidationError: fieldImmutableError, + expectValidationErrors: []string{fieldImmutableError}, }, "priority update": { oldObj: cpg, @@ -328,7 +396,7 @@ func TestStrategyUpdate(t *testing.T) { cpg.Spec.Priority = new(int32(2000)) return cpg }(), - expectValidationError: fieldImmutableError, + expectValidationErrors: []string{fieldImmutableError}, }, "parentCompositePodGroupName update not allowed": { oldObj: cpg, @@ -337,22 +405,33 @@ func TestStrategyUpdate(t *testing.T) { newCpg.Spec.ParentCompositePodGroupName = new("parent1") return newCpg }(), - expectValidationError: fieldImmutableError, + expectValidationErrors: []string{fieldImmutableError}, + }, + "changing preemptionPolicy not allowed with podgroup preemptionPolicy disabled": { + oldObj: cpgWithPreemptionPolicy(scheduling.PreemptNever), + newObj: cpgWithPreemptionPolicy(scheduling.PreemptLowerPriority), + expectValidationErrors: []string{forbiddenError, fieldImmutableError}, + }, + "changing preemptionPolicy not allowed with podgroup preemptionPolicy enabled": { + oldObj: cpgWithPreemptionPolicy(scheduling.PreemptNever), + newObj: cpgWithPreemptionPolicy(scheduling.PreemptLowerPriority), + enablePodGroupPreemptionPolicy: true, + expectValidationErrors: []string{fieldImmutableError}, }, "changing scheduling constraints not allowed": { - oldObj: compositePodGroupWithSchedulingConstraints("foo"), - newObj: compositePodGroupWithSchedulingConstraints(), - expectValidationError: fieldImmutableError, + oldObj: compositePodGroupWithSchedulingConstraints("foo"), + newObj: compositePodGroupWithSchedulingConstraints(), + expectValidationErrors: []string{fieldImmutableError}, }, "changing topology constraints not allowed": { - oldObj: compositePodGroupWithSchedulingConstraints("foo"), - newObj: compositePodGroupWithSchedulingConstraints(), - expectValidationError: fieldImmutableError, + oldObj: compositePodGroupWithSchedulingConstraints("foo"), + newObj: compositePodGroupWithSchedulingConstraints(), + expectValidationErrors: []string{fieldImmutableError}, }, "changing topology key not allowed": { - oldObj: compositePodGroupWithSchedulingConstraints("foo"), - newObj: compositePodGroupWithSchedulingConstraints("foobar"), - expectValidationError: fieldImmutableError, + oldObj: compositePodGroupWithSchedulingConstraints("foo"), + newObj: compositePodGroupWithSchedulingConstraints("foobar"), + expectValidationErrors: []string{fieldImmutableError}, }, } @@ -362,6 +441,7 @@ func TestStrategyUpdate(t *testing.T) { features.GenericWorkload: true, features.CompositePodGroup: true, features.TopologyAwareWorkloadScheduling: true, + features.PodGroupPreemptionPolicy: tc.enablePodGroupPreemptionPolicy, }) oldCpg := tc.oldObj.DeepCopy() newCpg := tc.newObj.DeepCopy() @@ -372,18 +452,20 @@ func TestStrategyUpdate(t *testing.T) { errs := strategy.ValidateUpdate(ctx, newCpg, oldCpg) errs = strategy.ValidateDeclaratively(ctx, newCpg, oldCpg, errs, operation.Update, strategy.DeclarativeValidationConfig(ctx, newCpg, oldCpg)) if len(errs) != 0 { - if tc.expectValidationError == "" { + if len(tc.expectValidationErrors) == 0 { t.Fatalf("unexpected error(s): %v", errs) } - if len(errs) != 1 { - t.Fatalf("exactly one error expected") + if len(errs) != len(tc.expectValidationErrors) { + t.Fatalf("expected %d errors, got %d", len(tc.expectValidationErrors), len(errs)) } - if errMsg := errs[0].Error(); !strings.Contains(errMsg, tc.expectValidationError) { - t.Fatalf("error %#v does not contain the expected message %q", errMsg, tc.expectValidationError) + for i, err := range errs { + if !strings.Contains(err.Error(), tc.expectValidationErrors[i]) { + t.Fatalf("error %#v does not contain the expected message %q", err.Error(), tc.expectValidationErrors[i]) + } } return } - if tc.expectValidationError != "" { + if len(tc.expectValidationErrors) != 0 { t.Fatal("expected validation error(s), got none") } }) diff --git a/pkg/registry/scheduling/workload/strategy.go b/pkg/registry/scheduling/workload/strategy.go index 8c417c9da96..b1a7173905b 100644 --- a/pkg/registry/scheduling/workload/strategy.go +++ b/pkg/registry/scheduling/workload/strategy.go @@ -138,7 +138,7 @@ func dropDisabledPodGroupTemplatesFields(templates, oldTemplates []scheduling.Po template := &templates[i] dropDisabledSchedulingConstraintsFields(template, oldTemplate) dropDisabledDRAWorkloadResourceClaimsFields(template, oldTemplate) - dropDisabledPreemptionPolicyFields(template, oldTemplate) + dropDisabledPGPreemptionPolicyFields(template, oldTemplate) } } @@ -151,6 +151,8 @@ func dropDisabledCompositePodGroupTemplatesFields(templates, oldTemplates []sche template := &templates[i] oldTemplate := oldTemplatesMap[template.Name] + dropDisabledCPGPreemptionPolicyFields(template, oldTemplate) + var cpgTemplates, oldCpgTemplates []scheduling.CompositePodGroupTemplate cpgTemplates = template.CompositePodGroupTemplates if oldTemplate != nil { @@ -190,10 +192,10 @@ func dropDisabledDRAWorkloadResourceClaimsFields(template, oldTemplate *scheduli template.ResourceClaims = nil } -// dropDisabledPreemptionPolicyFields removes the PreemptionPolicy field +// dropDisabledPGPreemptionPolicyFields removes the PreemptionPolicy field // from the PodGroupTemplate if the PodGroupPreemptionPolicy feature gate is disabled, // unless the field already used in the old PodGroupTemplate. -func dropDisabledPreemptionPolicyFields(template, oldTemplate *scheduling.PodGroupTemplate) { +func dropDisabledPGPreemptionPolicyFields(template, oldTemplate *scheduling.PodGroupTemplate) { if utilfeature.DefaultFeatureGate.Enabled(features.PodGroupPreemptionPolicy) || preemptionPolicyInUse(oldTemplate) { return } @@ -211,3 +213,17 @@ func draWorkloadResourceClaimsInUse(pgt *scheduling.PodGroupTemplate) bool { func preemptionPolicyInUse(pgt *scheduling.PodGroupTemplate) bool { return pgt != nil && pgt.PreemptionPolicy != nil } + +// dropDisabledCPGPreemptionPolicyFields removes the PreemptionPolicy field +// from the CompositePodGroupTemplate if the PodGroupPreemptionPolicy feature gate is disabled, +// unless the field already used in the old CompositePodGroupTemplate. +func dropDisabledCPGPreemptionPolicyFields(template, oldTemplate *scheduling.CompositePodGroupTemplate) { + if utilfeature.DefaultFeatureGate.Enabled(features.PodGroupPreemptionPolicy) || cpgPreemptionPolicyInUse(oldTemplate) { + return + } + template.PreemptionPolicy = nil +} + +func cpgPreemptionPolicyInUse(cpgt *scheduling.CompositePodGroupTemplate) bool { + return cpgt != nil && cpgt.PreemptionPolicy != nil +} diff --git a/pkg/registry/scheduling/workload/strategy_test.go b/pkg/registry/scheduling/workload/strategy_test.go index 34346b82ca5..f246152d203 100644 --- a/pkg/registry/scheduling/workload/strategy_test.go +++ b/pkg/registry/scheduling/workload/strategy_test.go @@ -91,6 +91,7 @@ func TestStrategyCreate(t *testing.T) { obj *scheduling.Workload expectObj *scheduling.Workload enableTopologyAwareScheduling bool + enableCompositePodGroup bool enablePodGroupPreemptionPolicy bool expectValidationError string }{ @@ -273,6 +274,210 @@ func TestStrategyCreate(t *testing.T) { enablePodGroupPreemptionPolicy: true, expectValidationError: supportedPoliciesError, }, + "drop cpg preemptionPolicy with PodGroupPreemptionPolicy disabled": { + obj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + policy := scheduling.PreemptNever + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: &policy, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + expectObj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + }, + "drop invalid cpg preemptionPolicy with PodGroupPreemptionPolicy disabled": { + obj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + policy := scheduling.PreemptionPolicy("Invalid") + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: &policy, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + expectObj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + }, + "cpg preemptionPolicy set (Never) with PodGroupPreemptionPolicy enabled": { + obj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + policy := scheduling.PreemptNever + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: &policy, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + expectObj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + policy := scheduling.PreemptNever + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: &policy, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + enablePodGroupPreemptionPolicy: true, + }, + "invalid cpg preemptionPolicy with PodGroupPreemptionPolicy enabled": { + obj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + policy := scheduling.PreemptionPolicy("Invalid") + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: &policy, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + enablePodGroupPreemptionPolicy: true, + expectValidationError: supportedPoliciesError, + }, } for name, tc := range testCases { @@ -283,6 +488,7 @@ func TestStrategyCreate(t *testing.T) { features.GenericWorkload: true, features.TopologyAwareWorkloadScheduling: tc.enableTopologyAwareScheduling, features.PodGroupPreemptionPolicy: tc.enablePodGroupPreemptionPolicy, + features.CompositePodGroup: tc.enableCompositePodGroup, }) Strategy.PrepareForCreate(ctx, workload) @@ -315,6 +521,7 @@ func TestStrategyUpdate(t *testing.T) { oldObj *scheduling.Workload newObj *scheduling.Workload enableTopologyAwareScheduling bool + enableCompositePodGroup bool enablePodGroupPreemptionPolicy bool expectValidationErrors []string expectWorkload *scheduling.Workload @@ -606,6 +813,242 @@ func TestStrategyUpdate(t *testing.T) { }(), expectValidationErrors: []string{fieldImmutableError}, }, + "changing cpg preemptionPolicy not allowed with PodGroupPreemptionPolicy disabled": { + oldObj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + policy := scheduling.PreemptNever + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: &policy, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + newObj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + policy := scheduling.PreemptLowerPriority + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: &policy, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + expectValidationErrors: []string{forbiddenError, fieldImmutableError}, + }, + "changing cpg preemptionPolicy not allowed with PodGroupPreemptionPolicy enabled": { + oldObj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + policy := scheduling.PreemptNever + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: &policy, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + newObj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + policy := scheduling.PreemptLowerPriority + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: &policy, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + enablePodGroupPreemptionPolicy: true, + expectValidationErrors: []string{fieldImmutableError}, + }, + "clearing cpg preemptionPolicy not allowed with PodGroupPreemptionPolicy enabled": { + oldObj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + policy := scheduling.PreemptNever + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: &policy, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + newObj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: nil, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + enablePodGroupPreemptionPolicy: true, + expectValidationErrors: []string{fieldImmutableError}, + }, + "clearing cpg preemptionPolicy not allowed with PodGroupPreemptionPolicy disabled": { + oldObj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + policy := scheduling.PreemptNever + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: &policy, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + newObj: func() *scheduling.Workload { + w := workload.DeepCopy() + w.Spec.PodGroupTemplates = nil + w.Spec.CompositePodGroupTemplates = []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PreemptionPolicy: nil, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + } + return w + }(), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + expectValidationErrors: []string{fieldImmutableError}, + }, } for name, tc := range testCases { @@ -614,6 +1057,7 @@ func TestStrategyUpdate(t *testing.T) { features.GenericWorkload: true, features.TopologyAwareWorkloadScheduling: tc.enableTopologyAwareScheduling, features.PodGroupPreemptionPolicy: tc.enablePodGroupPreemptionPolicy, + features.CompositePodGroup: tc.enableCompositePodGroup, }) oldWorkload := tc.oldObj.DeepCopy() newWorkload := tc.newObj.DeepCopy() @@ -898,3 +1342,147 @@ func TestDropCompositePodGroupTemplates(t *testing.T) { }) } } + +func TestDropCompositePodGroupTemplatePreemptionPolicy(t *testing.T) { + var noWorkload *scheduling.Workload + workloadWithoutPreemptionPolicy := &scheduling.Workload{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: metav1.NamespaceDefault, + }, + Spec: scheduling.WorkloadSpec{ + CompositePodGroupTemplates: []scheduling.CompositePodGroupTemplate{ + { + Name: "cpg-template", + SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ + Gang: &scheduling.CompositeGangSchedulingPolicy{ + MinGroupCount: 5, + }, + }, + PodGroupTemplates: []scheduling.PodGroupTemplate{ + { + Name: "pg-template", + SchedulingPolicy: scheduling.PodGroupSchedulingPolicy{ + Gang: &scheduling.GangSchedulingPolicy{ + MinCount: 5, + }, + }, + }, + }, + }, + }, + }, + } + workloadWithPreemptionPolicy := func() *scheduling.Workload { + w := workloadWithoutPreemptionPolicy.DeepCopy() + policy := scheduling.PreemptNever + w.Spec.CompositePodGroupTemplates[0].PreemptionPolicy = &policy + return w + }() + + tests := []struct { + description string + enabled bool + oldWorkload *scheduling.Workload + newWorkload *scheduling.Workload + wantWorkload *scheduling.Workload + }{ + { + description: "old with preemption / new with preemption / disabled", + oldWorkload: workloadWithPreemptionPolicy, + newWorkload: workloadWithPreemptionPolicy, + wantWorkload: workloadWithPreemptionPolicy, + }, + { + description: "old without preemption / new with preemption / disabled", + oldWorkload: workloadWithoutPreemptionPolicy, + newWorkload: workloadWithPreemptionPolicy, + wantWorkload: workloadWithoutPreemptionPolicy, + }, + { + description: "no old workload / new with preemption / disabled", + oldWorkload: noWorkload, + newWorkload: workloadWithPreemptionPolicy, + wantWorkload: workloadWithoutPreemptionPolicy, + }, + { + description: "old with preemption / new without preemption / disabled", + oldWorkload: workloadWithPreemptionPolicy, + newWorkload: workloadWithoutPreemptionPolicy, + wantWorkload: workloadWithoutPreemptionPolicy, + }, + { + description: "old without preemption / new without preemption / disabled", + oldWorkload: workloadWithoutPreemptionPolicy, + newWorkload: workloadWithoutPreemptionPolicy, + wantWorkload: workloadWithoutPreemptionPolicy, + }, + { + description: "no old workload / new without preemption / disabled", + oldWorkload: noWorkload, + newWorkload: workloadWithoutPreemptionPolicy, + wantWorkload: workloadWithoutPreemptionPolicy, + }, + { + description: "old with preemption / new with preemption / enabled", + enabled: true, + oldWorkload: workloadWithPreemptionPolicy, + newWorkload: workloadWithPreemptionPolicy, + wantWorkload: workloadWithPreemptionPolicy, + }, + { + description: "old without preemption / new with preemption / enabled", + enabled: true, + oldWorkload: workloadWithoutPreemptionPolicy, + newWorkload: workloadWithPreemptionPolicy, + wantWorkload: workloadWithPreemptionPolicy, + }, + { + description: "no old workload / new with preemption / enabled", + enabled: true, + oldWorkload: noWorkload, + newWorkload: workloadWithPreemptionPolicy, + wantWorkload: workloadWithPreemptionPolicy, + }, + { + description: "old with preemption / new without preemption / enabled", + enabled: true, + oldWorkload: workloadWithPreemptionPolicy, + newWorkload: workloadWithoutPreemptionPolicy, + wantWorkload: workloadWithoutPreemptionPolicy, + }, + { + description: "old without preemption / new without preemption / enabled", + enabled: true, + oldWorkload: workloadWithoutPreemptionPolicy, + newWorkload: workloadWithoutPreemptionPolicy, + wantWorkload: workloadWithoutPreemptionPolicy, + }, + { + description: "no old workload / new without preemption / enabled", + enabled: true, + oldWorkload: noWorkload, + newWorkload: workloadWithoutPreemptionPolicy, + wantWorkload: workloadWithoutPreemptionPolicy, + }, + } + + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ + features.PodGroupPreemptionPolicy: tc.enabled, + features.GenericWorkload: true, + features.CompositePodGroup: true, + features.TopologyAwareWorkloadScheduling: true, + }) + var oldSpec *scheduling.WorkloadSpec + if tc.oldWorkload != nil { + oldSpec = &tc.oldWorkload.Spec + } + dropDisabledWorkloadSpecFields(&tc.newWorkload.Spec, oldSpec) + if diff := cmp.Diff(tc.wantWorkload, tc.newWorkload); diff != "" { + t.Errorf("new Workload changed (- want, + got): %s", diff) + } + }) + } +} diff --git a/plugin/pkg/admission/priority/admission.go b/plugin/pkg/admission/priority/admission.go index 0f2140839f6..966384ccdf0 100644 --- a/plugin/pkg/admission/priority/admission.go +++ b/plugin/pkg/admission/priority/admission.go @@ -252,7 +252,7 @@ func (p *Plugin) admitCompositePodGroup(attributes admission.Attributes) error { return errors.NewBadRequest("resource was marked with kind CompositePodGroup but was unable to be converted") } - priorityClassName, priority, _, err := p.establishPriority(attributes, &cpg.Spec.PriorityClassName) + priorityClassName, priority, preemptionPolicy, err := p.establishPriority(attributes, &cpg.Spec.PriorityClassName) if err != nil { return err } @@ -262,6 +262,22 @@ func (p *Plugin) admitCompositePodGroup(attributes admission.Attributes) error { } cpg.Spec.Priority = &priority cpg.Spec.PriorityClassName = priorityClassName + + var schedulingPreemptionPolicy scheduling.PreemptionPolicy + if utilfeature.DefaultFeatureGate.Enabled(features.PodGroupPreemptionPolicy) && preemptionPolicy != nil { + switch *preemptionPolicy { + case apiv1.PreemptLowerPriority: + schedulingPreemptionPolicy = scheduling.PreemptLowerPriority + case apiv1.PreemptNever: + schedulingPreemptionPolicy = scheduling.PreemptNever + default: + return admission.NewForbidden(attributes, fmt.Errorf("preemptionPolicy set in the PriorityClass object (%v) must match one of the allowed values of PreemptionPolicy type in composite pod group", *preemptionPolicy)) + } + if cpg.Spec.PreemptionPolicy != nil && *cpg.Spec.PreemptionPolicy != schedulingPreemptionPolicy { + return admission.NewForbidden(attributes, fmt.Errorf("the string value of PreemptionPolicy (%s) must not be provided in composite pod group spec; priority admission controller computed %s from the given PriorityClass name", *cpg.Spec.PreemptionPolicy, schedulingPreemptionPolicy)) + } + cpg.Spec.PreemptionPolicy = &schedulingPreemptionPolicy + } return nil } diff --git a/plugin/pkg/admission/priority/admission_test.go b/plugin/pkg/admission/priority/admission_test.go index ca00147baed..d4122d2367a 100644 --- a/plugin/pkg/admission/priority/admission_test.go +++ b/plugin/pkg/admission/priority/admission_test.go @@ -1095,6 +1095,12 @@ func TestAdmitCompositePodGroup(t *testing.T) { return cpg } + cpgWithPreemptionPolicy := func(priorityClassName string, policy *scheduling.PreemptionPolicy) *scheduling.CompositePodGroup { + cpg := cpg(priorityClassName) + cpg.Spec.PreemptionPolicy = policy + return cpg + } + attributes := func(cpg *scheduling.CompositePodGroup, operation admission.Operation) admission.Attributes { var oldCpg runtime.Object var options runtime.Object = &metav1.CreateOptions{} @@ -1118,14 +1124,16 @@ func TestAdmitCompositePodGroup(t *testing.T) { } testCases := []struct { - name string - priorityClasses []*scheduling.PriorityClass - prepareCpg *scheduling.CompositePodGroup - operation admission.Operation - expectedPriorityClass string - expectedPriority int32 - enableCompositePodGroup bool - expectError bool + name string + priorityClasses []*scheduling.PriorityClass + prepareCpg *scheduling.CompositePodGroup + operation admission.Operation + expectedPriorityClass string + expectedPriority int32 + expectedPreemptionPolicy *scheduling.PreemptionPolicy + enableCompositePodGroup bool + enablePodGroupPreemptionPolicy bool + expectError bool }{ { name: "composite pod group with empty priorityClassName, accepted and set to global default", @@ -1192,6 +1200,46 @@ func TestAdmitCompositePodGroup(t *testing.T) { operation: admission.Update, enableCompositePodGroup: true, }, + { + name: "composite pod group with any preemptionPolicy but PodGroupPreemptionPolicy gate disabled, skips validation", + priorityClasses: []*scheduling.PriorityClass{preemptionPolicyClass}, + prepareCpg: cpgWithPreemptionPolicy(preemptionPolicyClass.Name, &schedulingPreemptNever), + operation: admission.Create, + expectedPriorityClass: "nopreemptionpolicy", + expectedPriority: preemptionPolicyClass.Value, + enableCompositePodGroup: true, + }, + { + name: "composite pod group with nil preemption policy", + priorityClasses: []*scheduling.PriorityClass{preemptionPolicyClass}, + prepareCpg: cpgWithPreemptionPolicy(preemptionPolicyClass.Name, nil), + operation: admission.Create, + expectedPriorityClass: "nopreemptionpolicy", + expectedPriority: preemptionPolicyClass.Value, + enableCompositePodGroup: true, + enablePodGroupPreemptionPolicy: true, + expectedPreemptionPolicy: &schedulingPreemptLowerPriority, + }, + { + name: "composite pod group with preemption policy that matches preemption policy resolved from priority class", + priorityClasses: []*scheduling.PriorityClass{preemptionPolicyClass}, + prepareCpg: cpgWithPreemptionPolicy(preemptionPolicyClass.Name, &schedulingPreemptLowerPriority), + operation: admission.Create, + expectedPriorityClass: "nopreemptionpolicy", + expectedPriority: preemptionPolicyClass.Value, + enableCompositePodGroup: true, + enablePodGroupPreemptionPolicy: true, + expectedPreemptionPolicy: &schedulingPreemptLowerPriority, + }, + { + name: "composite pod group with preemption policy that doesn't match preemption policy resolved from priority class", + priorityClasses: []*scheduling.PriorityClass{preemptionPolicyClass}, + prepareCpg: cpgWithPreemptionPolicy(preemptionPolicyClass.Name, &schedulingPreemptNever), + operation: admission.Create, + enableCompositePodGroup: true, + enablePodGroupPreemptionPolicy: true, + expectError: true, + }, } for _, tt := range testCases { @@ -1200,6 +1248,7 @@ func TestAdmitCompositePodGroup(t *testing.T) { features.GenericWorkload: tt.enableCompositePodGroup, features.TopologyAwareWorkloadScheduling: tt.enableCompositePodGroup, features.CompositePodGroup: tt.enableCompositePodGroup, + features.PodGroupPreemptionPolicy: tt.enablePodGroupPreemptionPolicy, }) admissionPlugin := NewPlugin() @@ -1220,6 +1269,11 @@ func TestAdmitCompositePodGroup(t *testing.T) { if *tt.prepareCpg.Spec.Priority != tt.expectedPriority { t.Errorf("CompositePodGroup Admit(), Priority = %v, want = %v", *tt.prepareCpg.Spec.Priority, tt.expectedPriority) } + if tt.expectedPreemptionPolicy != nil { + if tt.prepareCpg.Spec.PreemptionPolicy == nil || *tt.prepareCpg.Spec.PreemptionPolicy != *tt.expectedPreemptionPolicy { + t.Errorf("CompositePodGroup Admit(), PreemptionPolicy = %v, want = %v", tt.prepareCpg.Spec.PreemptionPolicy, tt.expectedPreemptionPolicy) + } + } } if tt.operation != admission.Create { if diff := cmp.Diff(tt.prepareCpg, cpgCopy); len(diff) > 0 { diff --git a/staging/src/k8s.io/api/scheduling/v1alpha3/generated.pb.go b/staging/src/k8s.io/api/scheduling/v1alpha3/generated.pb.go index eadbe883cb7..6dc6c066cab 100644 --- a/staging/src/k8s.io/api/scheduling/v1alpha3/generated.pb.go +++ b/staging/src/k8s.io/api/scheduling/v1alpha3/generated.pb.go @@ -31,12 +31,16 @@ import ( strings "strings" ) +func (m *AllCompositeDisruptionMode) Reset() { *m = AllCompositeDisruptionMode{} } + func (m *AllDisruptionMode) Reset() { *m = AllDisruptionMode{} } func (m *BasicSchedulingPolicy) Reset() { *m = BasicSchedulingPolicy{} } func (m *CompositeBasicSchedulingPolicy) Reset() { *m = CompositeBasicSchedulingPolicy{} } +func (m *CompositeDisruptionMode) Reset() { *m = CompositeDisruptionMode{} } + func (m *CompositeGangSchedulingPolicy) Reset() { *m = CompositeGangSchedulingPolicy{} } func (m *CompositePodGroup) Reset() { *m = CompositePodGroup{} } @@ -77,6 +81,8 @@ func (m *PodGroupStatus) Reset() { *m = PodGroupStatus{} } func (m *PodGroupTemplate) Reset() { *m = PodGroupTemplate{} } +func (m *SingleCompositeDisruptionMode) Reset() { *m = SingleCompositeDisruptionMode{} } + func (m *SingleDisruptionMode) Reset() { *m = SingleDisruptionMode{} } func (m *TopologyConstraint) Reset() { *m = TopologyConstraint{} } @@ -107,6 +113,29 @@ func (m *WorkloadReference) Reset() { *m = WorkloadReference{} } func (m *WorkloadSpec) Reset() { *m = WorkloadSpec{} } +func (m *AllCompositeDisruptionMode) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AllCompositeDisruptionMode) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AllCompositeDisruptionMode) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func (m *AllDisruptionMode) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -176,6 +205,53 @@ func (m *CompositeBasicSchedulingPolicy) MarshalToSizedBuffer(dAtA []byte) (int, return len(dAtA) - i, nil } +func (m *CompositeDisruptionMode) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CompositeDisruptionMode) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CompositeDisruptionMode) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.All != nil { + { + size, err := m.All.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Single != nil { + { + size, err := m.Single.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *CompositeGangSchedulingPolicy) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -406,6 +482,35 @@ func (m *CompositePodGroupSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.PreemptionPolicy != nil { + i -= len(*m.PreemptionPolicy) + copy(dAtA[i:], *m.PreemptionPolicy) + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.PreemptionPolicy))) + i-- + dAtA[i] = 0x42 + } + if m.Priority != nil { + i = encodeVarintGenerated(dAtA, i, uint64(*m.Priority)) + i-- + dAtA[i] = 0x38 + } + i -= len(m.PriorityClassName) + copy(dAtA[i:], m.PriorityClassName) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.PriorityClassName))) + i-- + dAtA[i] = 0x32 + if m.DisruptionMode != nil { + { + size, err := m.DisruptionMode.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } if m.SchedulingConstraints != nil { { size, err := m.SchedulingConstraints.MarshalToSizedBuffer(dAtA[:i]) @@ -416,18 +521,8 @@ func (m *CompositePodGroupSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x32 + dAtA[i] = 0x22 } - if m.Priority != nil { - i = encodeVarintGenerated(dAtA, i, uint64(*m.Priority)) - i-- - dAtA[i] = 0x28 - } - i -= len(m.PriorityClassName) - copy(dAtA[i:], m.PriorityClassName) - i = encodeVarintGenerated(dAtA, i, uint64(len(m.PriorityClassName))) - i-- - dAtA[i] = 0x22 { size, err := m.SchedulingPolicy.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -517,18 +612,6 @@ func (m *CompositePodGroupTemplate) MarshalToSizedBuffer(dAtA []byte) (int, erro _ = i var l int _ = l - if m.SchedulingConstraints != nil { - { - size, err := m.SchedulingConstraints.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenerated(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x3a - } if len(m.CompositePodGroupTemplates) > 0 { for iNdEx := len(m.CompositePodGroupTemplates) - 1; iNdEx >= 0; iNdEx-- { { @@ -540,7 +623,7 @@ func (m *CompositePodGroupTemplate) MarshalToSizedBuffer(dAtA []byte) (int, erro i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x32 + dAtA[i] = 0x4a } } if len(m.PodGroupTemplates) > 0 { @@ -554,19 +637,50 @@ func (m *CompositePodGroupTemplate) MarshalToSizedBuffer(dAtA []byte) (int, erro i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x2a + dAtA[i] = 0x42 } } + if m.PreemptionPolicy != nil { + i -= len(*m.PreemptionPolicy) + copy(dAtA[i:], *m.PreemptionPolicy) + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.PreemptionPolicy))) + i-- + dAtA[i] = 0x3a + } if m.Priority != nil { i = encodeVarintGenerated(dAtA, i, uint64(*m.Priority)) i-- - dAtA[i] = 0x20 + dAtA[i] = 0x30 } i -= len(m.PriorityClassName) copy(dAtA[i:], m.PriorityClassName) i = encodeVarintGenerated(dAtA, i, uint64(len(m.PriorityClassName))) i-- - dAtA[i] = 0x1a + dAtA[i] = 0x2a + if m.DisruptionMode != nil { + { + size, err := m.DisruptionMode.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.SchedulingConstraints != nil { + { + size, err := m.SchedulingConstraints.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } { size, err := m.SchedulingPolicy.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -1170,6 +1284,29 @@ func (m *PodGroupTemplate) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *SingleCompositeDisruptionMode) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SingleCompositeDisruptionMode) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SingleCompositeDisruptionMode) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func (m *SingleDisruptionMode) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1726,6 +1863,15 @@ func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } +func (m *AllCompositeDisruptionMode) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func (m *AllDisruptionMode) Size() (n int) { if m == nil { return 0 @@ -1753,6 +1899,23 @@ func (m *CompositeBasicSchedulingPolicy) Size() (n int) { return n } +func (m *CompositeDisruptionMode) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Single != nil { + l = m.Single.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.All != nil { + l = m.All.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *CompositeGangSchedulingPolicy) Size() (n int) { if m == nil { return 0 @@ -1843,13 +2006,21 @@ func (m *CompositePodGroupSpec) Size() (n int) { } l = m.SchedulingPolicy.Size() n += 1 + l + sovGenerated(uint64(l)) + if m.SchedulingConstraints != nil { + l = m.SchedulingConstraints.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.DisruptionMode != nil { + l = m.DisruptionMode.Size() + n += 1 + l + sovGenerated(uint64(l)) + } l = len(m.PriorityClassName) n += 1 + l + sovGenerated(uint64(l)) if m.Priority != nil { n += 1 + sovGenerated(uint64(*m.Priority)) } - if m.SchedulingConstraints != nil { - l = m.SchedulingConstraints.Size() + if m.PreemptionPolicy != nil { + l = len(*m.PreemptionPolicy) n += 1 + l + sovGenerated(uint64(l)) } return n @@ -1880,11 +2051,23 @@ func (m *CompositePodGroupTemplate) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) l = m.SchedulingPolicy.Size() n += 1 + l + sovGenerated(uint64(l)) + if m.SchedulingConstraints != nil { + l = m.SchedulingConstraints.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.DisruptionMode != nil { + l = m.DisruptionMode.Size() + n += 1 + l + sovGenerated(uint64(l)) + } l = len(m.PriorityClassName) n += 1 + l + sovGenerated(uint64(l)) if m.Priority != nil { n += 1 + sovGenerated(uint64(*m.Priority)) } + if m.PreemptionPolicy != nil { + l = len(*m.PreemptionPolicy) + n += 1 + l + sovGenerated(uint64(l)) + } if len(m.PodGroupTemplates) > 0 { for _, e := range m.PodGroupTemplates { l = e.Size() @@ -1897,10 +2080,6 @@ func (m *CompositePodGroupTemplate) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } - if m.SchedulingConstraints != nil { - l = m.SchedulingConstraints.Size() - n += 1 + l + sovGenerated(uint64(l)) - } return n } @@ -2128,6 +2307,15 @@ func (m *PodGroupTemplate) Size() (n int) { return n } +func (m *SingleCompositeDisruptionMode) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func (m *SingleDisruptionMode) Size() (n int) { if m == nil { return 0 @@ -2344,6 +2532,15 @@ func sovGenerated(x uint64) (n int) { func sozGenerated(x uint64) (n int) { return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (this *AllCompositeDisruptionMode) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&AllCompositeDisruptionMode{`, + `}`, + }, "") + return s +} func (this *AllDisruptionMode) String() string { if this == nil { return "nil" @@ -2371,6 +2568,17 @@ func (this *CompositeBasicSchedulingPolicy) String() string { }, "") return s } +func (this *CompositeDisruptionMode) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CompositeDisruptionMode{`, + `Single:` + strings.Replace(this.Single.String(), "SingleCompositeDisruptionMode", "SingleCompositeDisruptionMode", 1) + `,`, + `All:` + strings.Replace(this.All.String(), "AllCompositeDisruptionMode", "AllCompositeDisruptionMode", 1) + `,`, + `}`, + }, "") + return s +} func (this *CompositeGangSchedulingPolicy) String() string { if this == nil { return "nil" @@ -2443,9 +2651,11 @@ func (this *CompositePodGroupSpec) String() string { `ParentCompositePodGroupName:` + valueToStringGenerated(this.ParentCompositePodGroupName) + `,`, `WorkloadRef:` + strings.Replace(this.WorkloadRef.String(), "WorkloadReference", "WorkloadReference", 1) + `,`, `SchedulingPolicy:` + strings.Replace(strings.Replace(this.SchedulingPolicy.String(), "CompositePodGroupSchedulingPolicy", "CompositePodGroupSchedulingPolicy", 1), `&`, ``, 1) + `,`, + `SchedulingConstraints:` + strings.Replace(this.SchedulingConstraints.String(), "CompositePodGroupSchedulingConstraints", "CompositePodGroupSchedulingConstraints", 1) + `,`, + `DisruptionMode:` + strings.Replace(this.DisruptionMode.String(), "CompositeDisruptionMode", "CompositeDisruptionMode", 1) + `,`, `PriorityClassName:` + fmt.Sprintf("%v", this.PriorityClassName) + `,`, `Priority:` + valueToStringGenerated(this.Priority) + `,`, - `SchedulingConstraints:` + strings.Replace(this.SchedulingConstraints.String(), "CompositePodGroupSchedulingConstraints", "CompositePodGroupSchedulingConstraints", 1) + `,`, + `PreemptionPolicy:` + valueToStringGenerated(this.PreemptionPolicy) + `,`, `}`, }, "") return s @@ -2482,11 +2692,13 @@ func (this *CompositePodGroupTemplate) String() string { s := strings.Join([]string{`&CompositePodGroupTemplate{`, `Name:` + fmt.Sprintf("%v", this.Name) + `,`, `SchedulingPolicy:` + strings.Replace(strings.Replace(this.SchedulingPolicy.String(), "CompositePodGroupSchedulingPolicy", "CompositePodGroupSchedulingPolicy", 1), `&`, ``, 1) + `,`, + `SchedulingConstraints:` + strings.Replace(this.SchedulingConstraints.String(), "CompositePodGroupSchedulingConstraints", "CompositePodGroupSchedulingConstraints", 1) + `,`, + `DisruptionMode:` + strings.Replace(this.DisruptionMode.String(), "CompositeDisruptionMode", "CompositeDisruptionMode", 1) + `,`, `PriorityClassName:` + fmt.Sprintf("%v", this.PriorityClassName) + `,`, `Priority:` + valueToStringGenerated(this.Priority) + `,`, + `PreemptionPolicy:` + valueToStringGenerated(this.PreemptionPolicy) + `,`, `PodGroupTemplates:` + repeatedStringForPodGroupTemplates + `,`, `CompositePodGroupTemplates:` + repeatedStringForCompositePodGroupTemplates + `,`, - `SchedulingConstraints:` + strings.Replace(this.SchedulingConstraints.String(), "CompositePodGroupSchedulingConstraints", "CompositePodGroupSchedulingConstraints", 1) + `,`, `}`, }, "") return s @@ -2655,6 +2867,15 @@ func (this *PodGroupTemplate) String() string { }, "") return s } +func (this *SingleCompositeDisruptionMode) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&SingleCompositeDisruptionMode{`, + `}`, + }, "") + return s +} func (this *SingleDisruptionMode) String() string { if this == nil { return "nil" @@ -2840,6 +3061,56 @@ func valueToStringGenerated(v interface{}) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("*%v", pv) } +func (m *AllCompositeDisruptionMode) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AllCompositeDisruptionMode: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AllCompositeDisruptionMode: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *AllDisruptionMode) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -2990,6 +3261,128 @@ func (m *CompositeBasicSchedulingPolicy) Unmarshal(dAtA []byte) error { } return nil } +func (m *CompositeDisruptionMode) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CompositeDisruptionMode: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CompositeDisruptionMode: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Single", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Single == nil { + m.Single = &SingleCompositeDisruptionMode{} + } + if err := m.Single.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field All", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.All == nil { + m.All = &AllCompositeDisruptionMode{} + } + if err := m.All.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *CompositeGangSchedulingPolicy) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -3663,58 +4056,6 @@ func (m *CompositePodGroupSpec) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PriorityClassName", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthGenerated - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.PriorityClassName = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) - } - var v int32 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.Priority = &v - case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field SchedulingConstraints", wireType) } @@ -3750,6 +4091,127 @@ func (m *CompositePodGroupSpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DisruptionMode", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DisruptionMode == nil { + m.DisruptionMode = &CompositeDisruptionMode{} + } + if err := m.DisruptionMode.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PriorityClassName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PriorityClassName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) + } + var v int32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Priority = &v + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PreemptionPolicy", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := PreemptionPolicy(dAtA[iNdEx:postIndex]) + m.PreemptionPolicy = &s + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -3950,6 +4412,78 @@ func (m *CompositePodGroupTemplate) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SchedulingConstraints", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SchedulingConstraints == nil { + m.SchedulingConstraints = &CompositePodGroupSchedulingConstraints{} + } + if err := m.SchedulingConstraints.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DisruptionMode", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DisruptionMode == nil { + m.DisruptionMode = &CompositeDisruptionMode{} + } + if err := m.DisruptionMode.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field PriorityClassName", wireType) } @@ -3981,7 +4515,7 @@ func (m *CompositePodGroupTemplate) Unmarshal(dAtA []byte) error { } m.PriorityClassName = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 4: + case 6: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) } @@ -4001,7 +4535,40 @@ func (m *CompositePodGroupTemplate) Unmarshal(dAtA []byte) error { } } m.Priority = &v - case 5: + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PreemptionPolicy", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := PreemptionPolicy(dAtA[iNdEx:postIndex]) + m.PreemptionPolicy = &s + iNdEx = postIndex + case 8: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field PodGroupTemplates", wireType) } @@ -4035,7 +4602,7 @@ func (m *CompositePodGroupTemplate) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 6: + case 9: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field CompositePodGroupTemplates", wireType) } @@ -4069,42 +4636,6 @@ func (m *CompositePodGroupTemplate) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SchedulingConstraints", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenerated - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.SchedulingConstraints == nil { - m.SchedulingConstraints = &CompositePodGroupSchedulingConstraints{} - } - if err := m.SchedulingConstraints.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -5819,6 +6350,56 @@ func (m *PodGroupTemplate) Unmarshal(dAtA []byte) error { } return nil } +func (m *SingleCompositeDisruptionMode) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SingleCompositeDisruptionMode: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SingleCompositeDisruptionMode: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *SingleDisruptionMode) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/staging/src/k8s.io/api/scheduling/v1alpha3/generated.proto b/staging/src/k8s.io/api/scheduling/v1alpha3/generated.proto index 4ab970d7a1f..118a114bb6c 100644 --- a/staging/src/k8s.io/api/scheduling/v1alpha3/generated.proto +++ b/staging/src/k8s.io/api/scheduling/v1alpha3/generated.proto @@ -28,6 +28,11 @@ import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; // Package-wide variables from generator "generated". option go_package = "k8s.io/api/scheduling/v1alpha3"; +// AllCompositeDisruptionMode means that children of a CompositePodGroup can only be +// disrupted or preempted together. +message AllCompositeDisruptionMode { +} + // AllDisruptionMode specifies that children can only be disrupted together. message AllDisruptionMode { } @@ -42,6 +47,26 @@ message BasicSchedulingPolicy { message CompositeBasicSchedulingPolicy { } +// CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. +// Exactly one mode must be set. +// +// +union +message CompositeDisruptionMode { + // single specifies that children groups can be disrupted independently from each other. + // + // +optional + // +k8s:optional + // +k8s:unionMember + optional SingleCompositeDisruptionMode single = 1; + + // all specifies that all children groups can only be disrupted together. + // + // +optional + // +k8s:optional + // +k8s:unionMember + optional AllCompositeDisruptionMode all = 2; +} + // CompositeGangSchedulingPolicy indicates that the groups belonging to the composite group // should be scheduled using all-or-nothing semantics. message CompositeGangSchedulingPolicy { @@ -157,6 +182,26 @@ message CompositePodGroupSpec { // +k8s:immutable optional CompositePodGroupSchedulingPolicy schedulingPolicy = 3; + // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroup. + // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. + // This field is immutable. + // + // +optional + // +k8s:optional + // +k8s:immutable + optional CompositePodGroupSchedulingConstraints schedulingConstraints = 4; + + // disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. + // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. + // One of Single, All. Defaults to Single if unset. + // This field is immutable. + // + // +default={"single": {}} + // +optional + // +k8s:optional + // +k8s:immutable + optional CompositeDisruptionMode disruptionMode = 5; + // priorityClassName defines the priority that should be considered when scheduling this CompositePodGroup. // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. // If left unspecified, it is validated and resolved similarly to the PriorityClassName field in Pods @@ -168,7 +213,7 @@ message CompositePodGroupSpec { // +k8s:optional // +k8s:format=k8s-long-name // +k8s:immutable - optional string priorityClassName = 4; + optional string priorityClassName = 6; // priority is the value of priority of this composite pod group. Various system components // use this field to find the priority of the composite pod group. When Priority Admission @@ -181,16 +226,21 @@ message CompositePodGroupSpec { // +k8s:optional // +k8s:immutable // +k8s:maximum=1000000000 # HighestUserDefinablePriority - optional int32 priority = 5; + optional int32 priority = 7; - // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroup. - // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. + // preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. + // One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. + // When Priority Admission Controller is enabled, it populates this field from PriorityClassName, + // and defaults to PreemptLowerPriority if value is unset in PriorityClass. // This field is immutable. + // This field is available only when the PodGroupPreemptionPolicy feature gate is enabled. // + // +featureGate=PodGroupPreemptionPolicy // +optional - // +k8s:optional // +k8s:immutable - optional CompositePodGroupSchedulingConstraints schedulingConstraints = 6; + // +k8s:ifDisabled("PodGroupPreemptionPolicy")=+k8s:forbidden + // +k8s:ifEnabled("PodGroupPreemptionPolicy")=+k8s:optional + optional string preemptionPolicy = 8; } // CompositePodGroupStatus represents information about the status of a composite pod group. @@ -244,6 +294,23 @@ message CompositePodGroupTemplate { // +required optional CompositePodGroupSchedulingPolicy schedulingPolicy = 2; + // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. + // This field is immutable. + // + // +optional + // +k8s:optional + // +k8s:immutable + optional CompositePodGroupSchedulingConstraints schedulingConstraints = 3; + + // disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. + // One of Single, All. + // This field is immutable. + // + // +optional + // +k8s:optional + // +k8s:immutable + optional CompositeDisruptionMode disruptionMode = 4; + // priorityClassName indicates the priority that should be considered when scheduling // a composite pod group created from this template. If no priority class is specified, // admission control can set this to the global default priority class if it exists. @@ -255,7 +322,7 @@ message CompositePodGroupTemplate { // +k8s:optional // +k8s:format=k8s-long-name // +k8s:immutable - optional string priorityClassName = 3; + optional string priorityClassName = 5; // priority is the value of priority of composite pod groups created from this template. // Various system components use this field to find the priority of the composite pod group. @@ -268,7 +335,19 @@ message CompositePodGroupTemplate { // +k8s:optional // +k8s:maximum=1000000000 # HighestUserDefinablePriority // +k8s:immutable - optional int32 priority = 4; + optional int32 priority = 6; + + // preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. + // One of Never, PreemptLowerPriority. + // This field is immutable. + // This field is available only when the PodGroupPreemptionPolicy feature gate is enabled. + // + // +featureGate=PodGroupPreemptionPolicy + // +optional + // +k8s:immutable + // +k8s:ifDisabled("PodGroupPreemptionPolicy")=+k8s:forbidden + // +k8s:ifEnabled("PodGroupPreemptionPolicy")=+k8s:optional + optional string preemptionPolicy = 7; // podGroupTemplates is the list of templates for children PodGroups. // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates @@ -283,7 +362,7 @@ message CompositePodGroupTemplate { // +k8s:maxItems=8 // +k8s:update=NoAddItem // +k8s:update=NoRemoveItem - repeated PodGroupTemplate podGroupTemplates = 5; + repeated PodGroupTemplate podGroupTemplates = 8; // compositePodGroupTemplates is the list of templates for children CompositePodGroups. // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates @@ -298,15 +377,7 @@ message CompositePodGroupTemplate { // +k8s:maxItems=8 // +k8s:update=NoAddItem // +k8s:update=NoRemoveItem - repeated CompositePodGroupTemplate compositePodGroupTemplates = 6; - - // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. - // This field is immutable. - // - // +optional - // +k8s:optional - // +k8s:immutable - optional CompositePodGroupSchedulingConstraints schedulingConstraints = 7; + repeated CompositePodGroupTemplate compositePodGroupTemplates = 9; } // DisruptionMode defines how individual entities within a group can be disrupted. @@ -758,6 +829,11 @@ message PodGroupTemplate { optional string preemptionPolicy = 8; } +// SingleCompositeDisruptionMode means that individual children of a CompositePodGroup +// can be disrupted or preempted independently. +message SingleCompositeDisruptionMode { +} + // SingleDisruptionMode specifies that children can be disrupted independently. message SingleDisruptionMode { } diff --git a/staging/src/k8s.io/api/scheduling/v1alpha3/types.go b/staging/src/k8s.io/api/scheduling/v1alpha3/types.go index 20729e44982..6abec01de7c 100644 --- a/staging/src/k8s.io/api/scheduling/v1alpha3/types.go +++ b/staging/src/k8s.io/api/scheduling/v1alpha3/types.go @@ -251,6 +251,23 @@ type CompositePodGroupTemplate struct { // +required SchedulingPolicy CompositePodGroupSchedulingPolicy `json:"schedulingPolicy" protobuf:"bytes,2,opt,name=schedulingPolicy"` + // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. + // This field is immutable. + // + // +optional + // +k8s:optional + // +k8s:immutable + SchedulingConstraints *CompositePodGroupSchedulingConstraints `json:"schedulingConstraints,omitempty" protobuf:"bytes,3,opt,name=schedulingConstraints"` + + // disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. + // One of Single, All. + // This field is immutable. + // + // +optional + // +k8s:optional + // +k8s:immutable + DisruptionMode *CompositeDisruptionMode `json:"disruptionMode,omitempty" protobuf:"bytes,4,opt,name=disruptionMode"` + // priorityClassName indicates the priority that should be considered when scheduling // a composite pod group created from this template. If no priority class is specified, // admission control can set this to the global default priority class if it exists. @@ -262,7 +279,7 @@ type CompositePodGroupTemplate struct { // +k8s:optional // +k8s:format=k8s-long-name // +k8s:immutable - PriorityClassName string `json:"priorityClassName,omitempty" protobuf:"bytes,3,opt,name=priorityClassName"` + PriorityClassName string `json:"priorityClassName,omitempty" protobuf:"bytes,5,opt,name=priorityClassName"` // priority is the value of priority of composite pod groups created from this template. // Various system components use this field to find the priority of the composite pod group. @@ -275,7 +292,19 @@ type CompositePodGroupTemplate struct { // +k8s:optional // +k8s:maximum=1000000000 # HighestUserDefinablePriority // +k8s:immutable - Priority *int32 `json:"priority,omitempty" protobuf:"varint,4,opt,name=priority"` + Priority *int32 `json:"priority,omitempty" protobuf:"varint,6,opt,name=priority"` + + // preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. + // One of Never, PreemptLowerPriority. + // This field is immutable. + // This field is available only when the PodGroupPreemptionPolicy feature gate is enabled. + // + // +featureGate=PodGroupPreemptionPolicy + // +optional + // +k8s:immutable + // +k8s:ifDisabled("PodGroupPreemptionPolicy")=+k8s:forbidden + // +k8s:ifEnabled("PodGroupPreemptionPolicy")=+k8s:optional + PreemptionPolicy *PreemptionPolicy `json:"preemptionPolicy,omitempty" protobuf:"bytes,7,opt,name=preemptionPolicy"` // podGroupTemplates is the list of templates for children PodGroups. // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates @@ -290,7 +319,7 @@ type CompositePodGroupTemplate struct { // +k8s:maxItems=8 // +k8s:update=NoAddItem // +k8s:update=NoRemoveItem - PodGroupTemplates []PodGroupTemplate `json:"podGroupTemplates,omitempty" protobuf:"bytes,5,rep,name=podGroupTemplates"` + PodGroupTemplates []PodGroupTemplate `json:"podGroupTemplates,omitempty" protobuf:"bytes,8,rep,name=podGroupTemplates"` // compositePodGroupTemplates is the list of templates for children CompositePodGroups. // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates @@ -305,15 +334,7 @@ type CompositePodGroupTemplate struct { // +k8s:maxItems=8 // +k8s:update=NoAddItem // +k8s:update=NoRemoveItem - CompositePodGroupTemplates []CompositePodGroupTemplate `json:"compositePodGroupTemplates,omitempty" protobuf:"bytes,6,rep,name=compositePodGroupTemplates"` - - // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. - // This field is immutable. - // - // +optional - // +k8s:optional - // +k8s:immutable - SchedulingConstraints *CompositePodGroupSchedulingConstraints `json:"schedulingConstraints,omitempty" protobuf:"bytes,7,opt,name=schedulingConstraints"` + CompositePodGroupTemplates []CompositePodGroupTemplate `json:"compositePodGroupTemplates,omitempty" protobuf:"bytes,9,rep,name=compositePodGroupTemplates"` } // PodGroupSchedulingPolicy defines the scheduling configuration for a PodGroup. @@ -1061,6 +1082,26 @@ type CompositePodGroupSpec struct { // +k8s:immutable SchedulingPolicy CompositePodGroupSchedulingPolicy `json:"schedulingPolicy" protobuf:"bytes,3,opt,name=schedulingPolicy"` + // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroup. + // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. + // This field is immutable. + // + // +optional + // +k8s:optional + // +k8s:immutable + SchedulingConstraints *CompositePodGroupSchedulingConstraints `json:"schedulingConstraints,omitempty" protobuf:"bytes,4,opt,name=schedulingConstraints"` + + // disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. + // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. + // One of Single, All. Defaults to Single if unset. + // This field is immutable. + // + // +default={"single": {}} + // +optional + // +k8s:optional + // +k8s:immutable + DisruptionMode *CompositeDisruptionMode `json:"disruptionMode,omitempty" protobuf:"bytes,5,opt,name=disruptionMode"` + // priorityClassName defines the priority that should be considered when scheduling this CompositePodGroup. // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. // If left unspecified, it is validated and resolved similarly to the PriorityClassName field in Pods @@ -1072,7 +1113,7 @@ type CompositePodGroupSpec struct { // +k8s:optional // +k8s:format=k8s-long-name // +k8s:immutable - PriorityClassName string `json:"priorityClassName,omitempty" protobuf:"bytes,4,opt,name=priorityClassName"` + PriorityClassName string `json:"priorityClassName,omitempty" protobuf:"bytes,6,opt,name=priorityClassName"` // priority is the value of priority of this composite pod group. Various system components // use this field to find the priority of the composite pod group. When Priority Admission @@ -1085,16 +1126,21 @@ type CompositePodGroupSpec struct { // +k8s:optional // +k8s:immutable // +k8s:maximum=1000000000 # HighestUserDefinablePriority - Priority *int32 `json:"priority,omitempty" protobuf:"varint,5,opt,name=priority"` + Priority *int32 `json:"priority,omitempty" protobuf:"varint,7,opt,name=priority"` - // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroup. - // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. + // preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. + // One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. + // When Priority Admission Controller is enabled, it populates this field from PriorityClassName, + // and defaults to PreemptLowerPriority if value is unset in PriorityClass. // This field is immutable. + // This field is available only when the PodGroupPreemptionPolicy feature gate is enabled. // + // +featureGate=PodGroupPreemptionPolicy // +optional - // +k8s:optional // +k8s:immutable - SchedulingConstraints *CompositePodGroupSchedulingConstraints `json:"schedulingConstraints,omitempty" protobuf:"bytes,6,opt,name=schedulingConstraints"` + // +k8s:ifDisabled("PodGroupPreemptionPolicy")=+k8s:forbidden + // +k8s:ifEnabled("PodGroupPreemptionPolicy")=+k8s:optional + PreemptionPolicy *PreemptionPolicy `json:"preemptionPolicy,omitempty" protobuf:"bytes,8,opt,name=preemptionPolicy"` } // CompositePodGroupSchedulingPolicy defines the scheduling configuration for a CompositePodGroup. @@ -1144,6 +1190,38 @@ type CompositeGangSchedulingPolicy struct { MinGroupCount int32 `json:"minGroupCount" protobuf:"varint,1,req,name=minGroupCount"` } +// CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. +// Exactly one mode must be set. +// +// +union +type CompositeDisruptionMode struct { + // single specifies that children groups can be disrupted independently from each other. + // + // +optional + // +k8s:optional + // +k8s:unionMember + Single *SingleCompositeDisruptionMode `json:"single,omitempty" protobuf:"bytes,1,opt,name=single"` + + // all specifies that all children groups can only be disrupted together. + // + // +optional + // +k8s:optional + // +k8s:unionMember + All *AllCompositeDisruptionMode `json:"all,omitempty" protobuf:"bytes,2,opt,name=all"` +} + +// SingleCompositeDisruptionMode means that individual children of a CompositePodGroup +// can be disrupted or preempted independently. +type SingleCompositeDisruptionMode struct { + // This is intentionally empty. +} + +// AllCompositeDisruptionMode means that children of a CompositePodGroup can only be +// disrupted or preempted together. +type AllCompositeDisruptionMode struct { + // This is intentionally empty. +} + // CompositePodGroupStatus represents information about the status of a composite pod group. type CompositePodGroupStatus struct { // conditions represent the latest observations of the CompositePodGroup's state. diff --git a/staging/src/k8s.io/api/scheduling/v1alpha3/types_swagger_doc_generated.go b/staging/src/k8s.io/api/scheduling/v1alpha3/types_swagger_doc_generated.go index 0539b8131b1..8499ab545fe 100644 --- a/staging/src/k8s.io/api/scheduling/v1alpha3/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/scheduling/v1alpha3/types_swagger_doc_generated.go @@ -27,6 +27,14 @@ package v1alpha3 // Those methods can be generated by using hack/update-codegen.sh // AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. +var map_AllCompositeDisruptionMode = map[string]string{ + "": "AllCompositeDisruptionMode means that children of a CompositePodGroup can only be disrupted or preempted together.", +} + +func (AllCompositeDisruptionMode) SwaggerDoc() map[string]string { + return map_AllCompositeDisruptionMode +} + var map_AllDisruptionMode = map[string]string{ "": "AllDisruptionMode specifies that children can only be disrupted together.", } @@ -51,6 +59,16 @@ func (CompositeBasicSchedulingPolicy) SwaggerDoc() map[string]string { return map_CompositeBasicSchedulingPolicy } +var map_CompositeDisruptionMode = map[string]string{ + "": "CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. Exactly one mode must be set.", + "single": "single specifies that children groups can be disrupted independently from each other.", + "all": "all specifies that all children groups can only be disrupted together.", +} + +func (CompositeDisruptionMode) SwaggerDoc() map[string]string { + return map_CompositeDisruptionMode +} + var map_CompositeGangSchedulingPolicy = map[string]string{ "": "CompositeGangSchedulingPolicy indicates that the groups belonging to the composite group should be scheduled using all-or-nothing semantics.", "minGroupCount": "minGroupCount is the minimum number of child groups that must be schedulable or scheduled at the same time for the scheduler to admit the entire group. It must be a positive integer.", @@ -105,9 +123,11 @@ var map_CompositePodGroupSpec = map[string]string{ "parentCompositePodGroupName": "parentCompositePodGroupName contains the name of the parent composite pod group within the same namespace as this composite pod group. It must be a DNS name. If it's nil, then this composite pod group is a root of a workload's hierarchy. This field is immutable.", "workloadRef": "workloadRef references an optional CompositePodGroup template within the Workload object that was used to create the CompositePodGroup. This field is required. This field is immutable.", "schedulingPolicy": "schedulingPolicy defines the scheduling policy for this instance of the CompositePodGroup. Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. This field is immutable.", + "schedulingConstraints": "schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroup. Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. This field is immutable.", + "disruptionMode": "disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. One of Single, All. Defaults to Single if unset. This field is immutable.", "priorityClassName": "priorityClassName defines the priority that should be considered when scheduling this CompositePodGroup. Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. If left unspecified, it is validated and resolved similarly to the PriorityClassName field in Pods (i.e. if no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, the composite pod group's priority will be zero). This field is immutable.", "priority": "priority is the value of priority of this composite pod group. Various system components use this field to find the priority of the composite pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.", - "schedulingConstraints": "schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroup. Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. This field is immutable.", + "preemptionPolicy": "preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. When Priority Admission Controller is enabled, it populates this field from PriorityClassName, and defaults to PreemptLowerPriority if value is unset in PriorityClass. This field is immutable. This field is available only when the PodGroupPreemptionPolicy feature gate is enabled.", } func (CompositePodGroupSpec) SwaggerDoc() map[string]string { @@ -127,11 +147,13 @@ var map_CompositePodGroupTemplate = map[string]string{ "": "CompositePodGroupTemplate represents a template for a CompositePodGroup with a scheduling policy.", "name": "name is a unique identifier for the CompositePodGroupTemplate within the Workload. It must be a DNS label. This field is required.", "schedulingPolicy": "schedulingPolicy defines the scheduling policy for this template.", + "schedulingConstraints": "schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. This field is immutable.", + "disruptionMode": "disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. One of Single, All. This field is immutable.", "priorityClassName": "priorityClassName indicates the priority that should be considered when scheduling a composite pod group created from this template. If no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, composite pod groups created from this template will have the priority set to zero. This field is immutable.", "priority": "priority is the value of priority of composite pod groups created from this template. Various system components use this field to find the priority of the composite pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.", + "preemptionPolicy": "preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. One of Never, PreemptLowerPriority. This field is immutable. This field is available only when the PodGroupPreemptionPolicy feature gate is enabled.", "podGroupTemplates": "podGroupTemplates is the list of templates for children PodGroups. The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates or PodGroupTemplates must be set.", "compositePodGroupTemplates": "compositePodGroupTemplates is the list of templates for children CompositePodGroups. The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates or PodGroupTemplates must be set.", - "schedulingConstraints": "schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. This field is immutable.", } func (CompositePodGroupTemplate) SwaggerDoc() map[string]string { @@ -261,6 +283,14 @@ func (PodGroupTemplate) SwaggerDoc() map[string]string { return map_PodGroupTemplate } +var map_SingleCompositeDisruptionMode = map[string]string{ + "": "SingleCompositeDisruptionMode means that individual children of a CompositePodGroup can be disrupted or preempted independently.", +} + +func (SingleCompositeDisruptionMode) SwaggerDoc() map[string]string { + return map_SingleCompositeDisruptionMode +} + var map_SingleDisruptionMode = map[string]string{ "": "SingleDisruptionMode specifies that children can be disrupted independently.", } diff --git a/staging/src/k8s.io/api/scheduling/v1alpha3/zz_generated.deepcopy.go b/staging/src/k8s.io/api/scheduling/v1alpha3/zz_generated.deepcopy.go index dd9f0b5d903..57b581b1d94 100644 --- a/staging/src/k8s.io/api/scheduling/v1alpha3/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/scheduling/v1alpha3/zz_generated.deepcopy.go @@ -26,6 +26,22 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AllCompositeDisruptionMode) DeepCopyInto(out *AllCompositeDisruptionMode) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllCompositeDisruptionMode. +func (in *AllCompositeDisruptionMode) DeepCopy() *AllCompositeDisruptionMode { + if in == nil { + return nil + } + out := new(AllCompositeDisruptionMode) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AllDisruptionMode) DeepCopyInto(out *AllDisruptionMode) { *out = *in @@ -74,6 +90,32 @@ func (in *CompositeBasicSchedulingPolicy) DeepCopy() *CompositeBasicSchedulingPo return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CompositeDisruptionMode) DeepCopyInto(out *CompositeDisruptionMode) { + *out = *in + if in.Single != nil { + in, out := &in.Single, &out.Single + *out = new(SingleCompositeDisruptionMode) + **out = **in + } + if in.All != nil { + in, out := &in.All, &out.All + *out = new(AllCompositeDisruptionMode) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CompositeDisruptionMode. +func (in *CompositeDisruptionMode) DeepCopy() *CompositeDisruptionMode { + if in == nil { + return nil + } + out := new(CompositeDisruptionMode) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CompositeGangSchedulingPolicy) DeepCopyInto(out *CompositeGangSchedulingPolicy) { *out = *in @@ -212,15 +254,25 @@ func (in *CompositePodGroupSpec) DeepCopyInto(out *CompositePodGroupSpec) { **out = **in } in.SchedulingPolicy.DeepCopyInto(&out.SchedulingPolicy) + if in.SchedulingConstraints != nil { + in, out := &in.SchedulingConstraints, &out.SchedulingConstraints + *out = new(CompositePodGroupSchedulingConstraints) + (*in).DeepCopyInto(*out) + } + if in.DisruptionMode != nil { + in, out := &in.DisruptionMode, &out.DisruptionMode + *out = new(CompositeDisruptionMode) + (*in).DeepCopyInto(*out) + } if in.Priority != nil { in, out := &in.Priority, &out.Priority *out = new(int32) **out = **in } - if in.SchedulingConstraints != nil { - in, out := &in.SchedulingConstraints, &out.SchedulingConstraints - *out = new(CompositePodGroupSchedulingConstraints) - (*in).DeepCopyInto(*out) + if in.PreemptionPolicy != nil { + in, out := &in.PreemptionPolicy, &out.PreemptionPolicy + *out = new(PreemptionPolicy) + **out = **in } return } @@ -262,11 +314,26 @@ func (in *CompositePodGroupStatus) DeepCopy() *CompositePodGroupStatus { func (in *CompositePodGroupTemplate) DeepCopyInto(out *CompositePodGroupTemplate) { *out = *in in.SchedulingPolicy.DeepCopyInto(&out.SchedulingPolicy) + if in.SchedulingConstraints != nil { + in, out := &in.SchedulingConstraints, &out.SchedulingConstraints + *out = new(CompositePodGroupSchedulingConstraints) + (*in).DeepCopyInto(*out) + } + if in.DisruptionMode != nil { + in, out := &in.DisruptionMode, &out.DisruptionMode + *out = new(CompositeDisruptionMode) + (*in).DeepCopyInto(*out) + } if in.Priority != nil { in, out := &in.Priority, &out.Priority *out = new(int32) **out = **in } + if in.PreemptionPolicy != nil { + in, out := &in.PreemptionPolicy, &out.PreemptionPolicy + *out = new(PreemptionPolicy) + **out = **in + } if in.PodGroupTemplates != nil { in, out := &in.PodGroupTemplates, &out.PodGroupTemplates *out = make([]PodGroupTemplate, len(*in)) @@ -281,11 +348,6 @@ func (in *CompositePodGroupTemplate) DeepCopyInto(out *CompositePodGroupTemplate (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.SchedulingConstraints != nil { - in, out := &in.SchedulingConstraints, &out.SchedulingConstraints - *out = new(CompositePodGroupSchedulingConstraints) - (*in).DeepCopyInto(*out) - } return } @@ -624,6 +686,22 @@ func (in *PodGroupTemplate) DeepCopy() *PodGroupTemplate { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SingleCompositeDisruptionMode) DeepCopyInto(out *SingleCompositeDisruptionMode) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SingleCompositeDisruptionMode. +func (in *SingleCompositeDisruptionMode) DeepCopy() *SingleCompositeDisruptionMode { + if in == nil { + return nil + } + out := new(SingleCompositeDisruptionMode) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SingleDisruptionMode) DeepCopyInto(out *SingleDisruptionMode) { *out = *in diff --git a/staging/src/k8s.io/api/scheduling/v1alpha3/zz_generated.model_name.go b/staging/src/k8s.io/api/scheduling/v1alpha3/zz_generated.model_name.go index 21c573d5d0b..10728460348 100644 --- a/staging/src/k8s.io/api/scheduling/v1alpha3/zz_generated.model_name.go +++ b/staging/src/k8s.io/api/scheduling/v1alpha3/zz_generated.model_name.go @@ -21,6 +21,11 @@ limitations under the License. package v1alpha3 +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in AllCompositeDisruptionMode) OpenAPIModelName() string { + return "io.k8s.api.scheduling.v1alpha3.AllCompositeDisruptionMode" +} + // OpenAPIModelName returns the OpenAPI model name for this type. func (in AllDisruptionMode) OpenAPIModelName() string { return "io.k8s.api.scheduling.v1alpha3.AllDisruptionMode" @@ -36,6 +41,11 @@ func (in CompositeBasicSchedulingPolicy) OpenAPIModelName() string { return "io.k8s.api.scheduling.v1alpha3.CompositeBasicSchedulingPolicy" } +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in CompositeDisruptionMode) OpenAPIModelName() string { + return "io.k8s.api.scheduling.v1alpha3.CompositeDisruptionMode" +} + // OpenAPIModelName returns the OpenAPI model name for this type. func (in CompositeGangSchedulingPolicy) OpenAPIModelName() string { return "io.k8s.api.scheduling.v1alpha3.CompositeGangSchedulingPolicy" @@ -131,6 +141,11 @@ func (in PodGroupTemplate) OpenAPIModelName() string { return "io.k8s.api.scheduling.v1alpha3.PodGroupTemplate" } +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in SingleCompositeDisruptionMode) OpenAPIModelName() string { + return "io.k8s.api.scheduling.v1alpha3.SingleCompositeDisruptionMode" +} + // OpenAPIModelName returns the OpenAPI model name for this type. func (in SingleDisruptionMode) OpenAPIModelName() string { return "io.k8s.api.scheduling.v1alpha3.SingleDisruptionMode" diff --git a/staging/src/k8s.io/api/scheduling/v1alpha3/zz_generated.validations.go b/staging/src/k8s.io/api/scheduling/v1alpha3/zz_generated.validations.go index 861b344e4c6..3612b7a8250 100644 --- a/staging/src/k8s.io/api/scheduling/v1alpha3/zz_generated.validations.go +++ b/staging/src/k8s.io/api/scheduling/v1alpha3/zz_generated.validations.go @@ -34,6 +34,89 @@ import ( field "k8s.io/apimachinery/pkg/util/validation/field" ) +var unionMembershipFor_k8s_io_api_scheduling_v1alpha3_CompositeDisruptionMode_ = validate.NewUnionMembership(validate.NewUnionMember("single"), validate.NewUnionMember("all")) + +// Validate_CompositeDisruptionMode validates an instance of CompositeDisruptionMode according +// to declarative validation rules in the API schema. +func Validate_CompositeDisruptionMode( + ctx context.Context, op operation.Operation, fldPath *field.Path, + obj, oldObj *CompositeDisruptionMode) (errs field.ErrorList) { + + if e := validate.Union(ctx, op, fldPath, obj, oldObj, unionMembershipFor_k8s_io_api_scheduling_v1alpha3_CompositeDisruptionMode_, + func(obj *CompositeDisruptionMode) bool { + if obj == nil { + return false + } + return obj.Single != nil + }, + func(obj *CompositeDisruptionMode) bool { + if obj == nil { + return false + } + return obj.All != nil + }); len(e) != 0 { + errs = append(errs, e...) + } + + { // field CompositeDisruptionMode.Single + fn := func( + fldPath *field.Path, + obj, oldObj *SingleCompositeDisruptionMode, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *CompositeDisruptionMode) *SingleCompositeDisruptionMode { + return oldObj.Single + }) + errs = append(errs, fn(fldPath.Child("single"), obj.Single, oldVal, oldObj != nil)...) + } + + { // field CompositeDisruptionMode.All + fn := func( + fldPath *field.Path, + obj, oldObj *AllCompositeDisruptionMode, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *CompositeDisruptionMode) *AllCompositeDisruptionMode { + return oldObj.All + }) + errs = append(errs, fn(fldPath.Child("all"), obj.All, oldVal, oldObj != nil)...) + } + + return errs +} + // Validate_CompositeGangSchedulingPolicy validates an instance of CompositeGangSchedulingPolicy according // to declarative validation rules in the API schema. func Validate_CompositeGangSchedulingPolicy( @@ -397,6 +480,76 @@ func Validate_CompositePodGroupSpec( errs = append(errs, fn(fldPath.Child("schedulingPolicy"), &obj.SchedulingPolicy, oldVal, oldObj != nil)...) } + { // field CompositePodGroupSpec.SchedulingConstraints + fn := func( + fldPath *field.Path, + obj, oldObj *CompositePodGroupSchedulingConstraints, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_CompositePodGroupSchedulingConstraints(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *CompositePodGroupSpec) *CompositePodGroupSchedulingConstraints { + return oldObj.SchedulingConstraints + }) + errs = append(errs, fn(fldPath.Child("schedulingConstraints"), obj.SchedulingConstraints, oldVal, oldObj != nil)...) + } + + { // field CompositePodGroupSpec.DisruptionMode + fn := func( + fldPath *field.Path, + obj, oldObj *CompositeDisruptionMode, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + // optional fields with default values are effectively required + if e := validate.RequiredPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_CompositeDisruptionMode(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *CompositePodGroupSpec) *CompositeDisruptionMode { + return oldObj.DisruptionMode + }) + errs = append(errs, fn(fldPath.Child("disruptionMode"), obj.DisruptionMode, oldVal, oldObj != nil)...) + } + { // field CompositePodGroupSpec.PriorityClassName fn := func( fldPath *field.Path, @@ -467,38 +620,45 @@ func Validate_CompositePodGroupSpec( errs = append(errs, fn(fldPath.Child("priority"), obj.Priority, oldVal, oldObj != nil)...) } - { // field CompositePodGroupSpec.SchedulingConstraints + { // field CompositePodGroupSpec.PreemptionPolicy fn := func( fldPath *field.Path, - obj, oldObj *CompositePodGroupSchedulingConstraints, + obj, oldObj *PreemptionPolicy, oldValueCorrelated bool) (errs field.ErrorList) { // don't revalidate unchanged data if oldValueCorrelated && op.Type == operation.Update { - if equality.Semantic.DeepEqual(obj, oldObj) { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { return nil } } // call field-attached validations earlyReturn := false - if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", false, validate.ForbiddenPointer).MarkShortCircuit(); len(e) != 0 { errs = append(errs, e...) earlyReturn = true } - if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", false, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", true, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) earlyReturn = true } if earlyReturn { return // do not proceed } // call the type's validation function - errs = append(errs, Validate_CompositePodGroupSchedulingConstraints(ctx, op, fldPath, obj, oldObj)...) + errs = append(errs, Validate_PreemptionPolicy(ctx, op, fldPath, obj, oldObj)...) return } oldVal := safe.Field(oldObj, - func(oldObj *CompositePodGroupSpec) *CompositePodGroupSchedulingConstraints { - return oldObj.SchedulingConstraints + func(oldObj *CompositePodGroupSpec) *PreemptionPolicy { + return oldObj.PreemptionPolicy }) - errs = append(errs, fn(fldPath.Child("schedulingConstraints"), obj.SchedulingConstraints, oldVal, oldObj != nil)...) + errs = append(errs, fn(fldPath.Child("preemptionPolicy"), obj.PreemptionPolicy, oldVal, oldObj != nil)...) } return errs @@ -611,6 +771,74 @@ func Validate_CompositePodGroupTemplate( errs = append(errs, fn(fldPath.Child("schedulingPolicy"), &obj.SchedulingPolicy, oldVal, oldObj != nil)...) } + { // field CompositePodGroupTemplate.SchedulingConstraints + fn := func( + fldPath *field.Path, + obj, oldObj *CompositePodGroupSchedulingConstraints, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_CompositePodGroupSchedulingConstraints(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *CompositePodGroupTemplate) *CompositePodGroupSchedulingConstraints { + return oldObj.SchedulingConstraints + }) + errs = append(errs, fn(fldPath.Child("schedulingConstraints"), obj.SchedulingConstraints, oldVal, oldObj != nil)...) + } + + { // field CompositePodGroupTemplate.DisruptionMode + fn := func( + fldPath *field.Path, + obj, oldObj *CompositeDisruptionMode, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if equality.Semantic.DeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_CompositeDisruptionMode(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *CompositePodGroupTemplate) *CompositeDisruptionMode { + return oldObj.DisruptionMode + }) + errs = append(errs, fn(fldPath.Child("disruptionMode"), obj.DisruptionMode, oldVal, oldObj != nil)...) + } + { // field CompositePodGroupTemplate.PriorityClassName fn := func( fldPath *field.Path, @@ -681,6 +909,47 @@ func Validate_CompositePodGroupTemplate( errs = append(errs, fn(fldPath.Child("priority"), obj.Priority, oldVal, oldObj != nil)...) } + { // field CompositePodGroupTemplate.PreemptionPolicy + fn := func( + fldPath *field.Path, + obj, oldObj *PreemptionPolicy, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", false, validate.ForbiddenPointer).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", false, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if e := validate.IfOption(ctx, op, fldPath, obj, oldObj, "PodGroupPreemptionPolicy", true, validate.OptionalPointer).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + // call the type's validation function + errs = append(errs, Validate_PreemptionPolicy(ctx, op, fldPath, obj, oldObj)...) + return + } + oldVal := safe.Field(oldObj, + func(oldObj *CompositePodGroupTemplate) *PreemptionPolicy { + return oldObj.PreemptionPolicy + }) + errs = append(errs, fn(fldPath.Child("preemptionPolicy"), obj.PreemptionPolicy, oldVal, oldObj != nil)...) + } + { // field CompositePodGroupTemplate.PodGroupTemplates fn := func( fldPath *field.Path, @@ -775,40 +1044,6 @@ func Validate_CompositePodGroupTemplate( errs = append(errs, fn(fldPath.Child("compositePodGroupTemplates"), obj.CompositePodGroupTemplates, oldVal, oldObj != nil)...) } - { // field CompositePodGroupTemplate.SchedulingConstraints - fn := func( - fldPath *field.Path, - obj, oldObj *CompositePodGroupSchedulingConstraints, - oldValueCorrelated bool) (errs field.ErrorList) { - // don't revalidate unchanged data - if oldValueCorrelated && op.Type == operation.Update { - if equality.Semantic.DeepEqual(obj, oldObj) { - return nil - } - } - // call field-attached validations - earlyReturn := false - if e := validate.Immutable(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { - errs = append(errs, e...) - earlyReturn = true - } - if e := validate.OptionalPointer(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { - earlyReturn = true - } - if earlyReturn { - return // do not proceed - } - // call the type's validation function - errs = append(errs, Validate_CompositePodGroupSchedulingConstraints(ctx, op, fldPath, obj, oldObj)...) - return - } - oldVal := safe.Field(oldObj, - func(oldObj *CompositePodGroupTemplate) *CompositePodGroupSchedulingConstraints { - return oldObj.SchedulingConstraints - }) - errs = append(errs, fn(fldPath.Child("schedulingConstraints"), obj.SchedulingConstraints, oldVal, oldObj != nil)...) - } - return errs } diff --git a/staging/src/k8s.io/api/scheduling/v1beta1/generated.pb.go b/staging/src/k8s.io/api/scheduling/v1beta1/generated.pb.go index 18b6f8d2403..d8572d3c011 100644 --- a/staging/src/k8s.io/api/scheduling/v1beta1/generated.pb.go +++ b/staging/src/k8s.io/api/scheduling/v1beta1/generated.pb.go @@ -32,12 +32,16 @@ import ( strings "strings" ) +func (m *AllCompositeDisruptionMode) Reset() { *m = AllCompositeDisruptionMode{} } + func (m *AllDisruptionMode) Reset() { *m = AllDisruptionMode{} } func (m *BasicSchedulingPolicy) Reset() { *m = BasicSchedulingPolicy{} } func (m *CompositeBasicSchedulingPolicy) Reset() { *m = CompositeBasicSchedulingPolicy{} } +func (m *CompositeDisruptionMode) Reset() { *m = CompositeDisruptionMode{} } + func (m *CompositeGangSchedulingPolicy) Reset() { *m = CompositeGangSchedulingPolicy{} } func (m *CompositePodGroupSchedulingConstraints) Reset() { @@ -74,6 +78,8 @@ func (m *PriorityClass) Reset() { *m = PriorityClass{} } func (m *PriorityClassList) Reset() { *m = PriorityClassList{} } +func (m *SingleCompositeDisruptionMode) Reset() { *m = SingleCompositeDisruptionMode{} } + func (m *SingleDisruptionMode) Reset() { *m = SingleDisruptionMode{} } func (m *TopologyConstraint) Reset() { *m = TopologyConstraint{} } @@ -88,6 +94,29 @@ func (m *WorkloadReference) Reset() { *m = WorkloadReference{} } func (m *WorkloadSpec) Reset() { *m = WorkloadSpec{} } +func (m *AllCompositeDisruptionMode) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AllCompositeDisruptionMode) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AllCompositeDisruptionMode) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func (m *AllDisruptionMode) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -157,6 +186,53 @@ func (m *CompositeBasicSchedulingPolicy) MarshalToSizedBuffer(dAtA []byte) (int, return len(dAtA) - i, nil } +func (m *CompositeDisruptionMode) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CompositeDisruptionMode) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CompositeDisruptionMode) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.All != nil { + { + size, err := m.All.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Single != nil { + { + size, err := m.Single.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *CompositeGangSchedulingPolicy) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -287,18 +363,6 @@ func (m *CompositePodGroupTemplate) MarshalToSizedBuffer(dAtA []byte) (int, erro _ = i var l int _ = l - if m.SchedulingConstraints != nil { - { - size, err := m.SchedulingConstraints.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenerated(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x3a - } if len(m.CompositePodGroupTemplates) > 0 { for iNdEx := len(m.CompositePodGroupTemplates) - 1; iNdEx >= 0; iNdEx-- { { @@ -310,7 +374,7 @@ func (m *CompositePodGroupTemplate) MarshalToSizedBuffer(dAtA []byte) (int, erro i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x32 + dAtA[i] = 0x4a } } if len(m.PodGroupTemplates) > 0 { @@ -324,19 +388,50 @@ func (m *CompositePodGroupTemplate) MarshalToSizedBuffer(dAtA []byte) (int, erro i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x2a + dAtA[i] = 0x42 } } + if m.PreemptionPolicy != nil { + i -= len(*m.PreemptionPolicy) + copy(dAtA[i:], *m.PreemptionPolicy) + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.PreemptionPolicy))) + i-- + dAtA[i] = 0x3a + } if m.Priority != nil { i = encodeVarintGenerated(dAtA, i, uint64(*m.Priority)) i-- - dAtA[i] = 0x20 + dAtA[i] = 0x30 } i -= len(m.PriorityClassName) copy(dAtA[i:], m.PriorityClassName) i = encodeVarintGenerated(dAtA, i, uint64(len(m.PriorityClassName))) i-- - dAtA[i] = 0x1a + dAtA[i] = 0x2a + if m.DisruptionMode != nil { + { + size, err := m.DisruptionMode.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.SchedulingConstraints != nil { + { + size, err := m.SchedulingConstraints.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } { size, err := m.SchedulingPolicy.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -1043,6 +1138,29 @@ func (m *PriorityClassList) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *SingleCompositeDisruptionMode) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SingleCompositeDisruptionMode) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SingleCompositeDisruptionMode) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func (m *SingleDisruptionMode) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1329,6 +1447,15 @@ func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } +func (m *AllCompositeDisruptionMode) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func (m *AllDisruptionMode) Size() (n int) { if m == nil { return 0 @@ -1356,6 +1483,23 @@ func (m *CompositeBasicSchedulingPolicy) Size() (n int) { return n } +func (m *CompositeDisruptionMode) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Single != nil { + l = m.Single.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.All != nil { + l = m.All.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *CompositeGangSchedulingPolicy) Size() (n int) { if m == nil { return 0 @@ -1408,11 +1552,23 @@ func (m *CompositePodGroupTemplate) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) l = m.SchedulingPolicy.Size() n += 1 + l + sovGenerated(uint64(l)) + if m.SchedulingConstraints != nil { + l = m.SchedulingConstraints.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.DisruptionMode != nil { + l = m.DisruptionMode.Size() + n += 1 + l + sovGenerated(uint64(l)) + } l = len(m.PriorityClassName) n += 1 + l + sovGenerated(uint64(l)) if m.Priority != nil { n += 1 + sovGenerated(uint64(*m.Priority)) } + if m.PreemptionPolicy != nil { + l = len(*m.PreemptionPolicy) + n += 1 + l + sovGenerated(uint64(l)) + } if len(m.PodGroupTemplates) > 0 { for _, e := range m.PodGroupTemplates { l = e.Size() @@ -1425,10 +1581,6 @@ func (m *CompositePodGroupTemplate) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } - if m.SchedulingConstraints != nil { - l = m.SchedulingConstraints.Size() - n += 1 + l + sovGenerated(uint64(l)) - } return n } @@ -1692,6 +1844,15 @@ func (m *PriorityClassList) Size() (n int) { return n } +func (m *SingleCompositeDisruptionMode) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func (m *SingleDisruptionMode) Size() (n int) { if m == nil { return 0 @@ -1801,6 +1962,15 @@ func sovGenerated(x uint64) (n int) { func sozGenerated(x uint64) (n int) { return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (this *AllCompositeDisruptionMode) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&AllCompositeDisruptionMode{`, + `}`, + }, "") + return s +} func (this *AllDisruptionMode) String() string { if this == nil { return "nil" @@ -1828,6 +1998,17 @@ func (this *CompositeBasicSchedulingPolicy) String() string { }, "") return s } +func (this *CompositeDisruptionMode) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CompositeDisruptionMode{`, + `Single:` + strings.Replace(this.Single.String(), "SingleCompositeDisruptionMode", "SingleCompositeDisruptionMode", 1) + `,`, + `All:` + strings.Replace(this.All.String(), "AllCompositeDisruptionMode", "AllCompositeDisruptionMode", 1) + `,`, + `}`, + }, "") + return s +} func (this *CompositeGangSchedulingPolicy) String() string { if this == nil { return "nil" @@ -1881,11 +2062,13 @@ func (this *CompositePodGroupTemplate) String() string { s := strings.Join([]string{`&CompositePodGroupTemplate{`, `Name:` + fmt.Sprintf("%v", this.Name) + `,`, `SchedulingPolicy:` + strings.Replace(strings.Replace(this.SchedulingPolicy.String(), "CompositePodGroupSchedulingPolicy", "CompositePodGroupSchedulingPolicy", 1), `&`, ``, 1) + `,`, + `SchedulingConstraints:` + strings.Replace(this.SchedulingConstraints.String(), "CompositePodGroupSchedulingConstraints", "CompositePodGroupSchedulingConstraints", 1) + `,`, + `DisruptionMode:` + strings.Replace(this.DisruptionMode.String(), "CompositeDisruptionMode", "CompositeDisruptionMode", 1) + `,`, `PriorityClassName:` + fmt.Sprintf("%v", this.PriorityClassName) + `,`, `Priority:` + valueToStringGenerated(this.Priority) + `,`, + `PreemptionPolicy:` + valueToStringGenerated(this.PreemptionPolicy) + `,`, `PodGroupTemplates:` + repeatedStringForPodGroupTemplates + `,`, `CompositePodGroupTemplates:` + repeatedStringForCompositePodGroupTemplates + `,`, - `SchedulingConstraints:` + strings.Replace(this.SchedulingConstraints.String(), "CompositePodGroupSchedulingConstraints", "CompositePodGroupSchedulingConstraints", 1) + `,`, `}`, }, "") return s @@ -2084,6 +2267,15 @@ func (this *PriorityClassList) String() string { }, "") return s } +func (this *SingleCompositeDisruptionMode) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&SingleCompositeDisruptionMode{`, + `}`, + }, "") + return s +} func (this *SingleDisruptionMode) String() string { if this == nil { return "nil" @@ -2183,6 +2375,56 @@ func valueToStringGenerated(v interface{}) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("*%v", pv) } +func (m *AllCompositeDisruptionMode) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AllCompositeDisruptionMode: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AllCompositeDisruptionMode: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *AllDisruptionMode) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -2333,6 +2575,128 @@ func (m *CompositeBasicSchedulingPolicy) Unmarshal(dAtA []byte) error { } return nil } +func (m *CompositeDisruptionMode) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CompositeDisruptionMode: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CompositeDisruptionMode: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Single", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Single == nil { + m.Single = &SingleCompositeDisruptionMode{} + } + if err := m.Single.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field All", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.All == nil { + m.All = &AllCompositeDisruptionMode{} + } + if err := m.All.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *CompositeGangSchedulingPolicy) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -2703,6 +3067,78 @@ func (m *CompositePodGroupTemplate) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SchedulingConstraints", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SchedulingConstraints == nil { + m.SchedulingConstraints = &CompositePodGroupSchedulingConstraints{} + } + if err := m.SchedulingConstraints.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DisruptionMode", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DisruptionMode == nil { + m.DisruptionMode = &CompositeDisruptionMode{} + } + if err := m.DisruptionMode.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field PriorityClassName", wireType) } @@ -2734,7 +3170,7 @@ func (m *CompositePodGroupTemplate) Unmarshal(dAtA []byte) error { } m.PriorityClassName = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 4: + case 6: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) } @@ -2754,7 +3190,40 @@ func (m *CompositePodGroupTemplate) Unmarshal(dAtA []byte) error { } } m.Priority = &v - case 5: + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PreemptionPolicy", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := PreemptionPolicy(dAtA[iNdEx:postIndex]) + m.PreemptionPolicy = &s + iNdEx = postIndex + case 8: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field PodGroupTemplates", wireType) } @@ -2788,7 +3257,7 @@ func (m *CompositePodGroupTemplate) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 6: + case 9: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field CompositePodGroupTemplates", wireType) } @@ -2822,42 +3291,6 @@ func (m *CompositePodGroupTemplate) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SchedulingConstraints", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenerated - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.SchedulingConstraints == nil { - m.SchedulingConstraints = &CompositePodGroupSchedulingConstraints{} - } - if err := m.SchedulingConstraints.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -4876,6 +5309,56 @@ func (m *PriorityClassList) Unmarshal(dAtA []byte) error { } return nil } +func (m *SingleCompositeDisruptionMode) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SingleCompositeDisruptionMode: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SingleCompositeDisruptionMode: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *SingleDisruptionMode) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/staging/src/k8s.io/api/scheduling/v1beta1/generated.proto b/staging/src/k8s.io/api/scheduling/v1beta1/generated.proto index 3ccd857d053..0e1e2d981e6 100644 --- a/staging/src/k8s.io/api/scheduling/v1beta1/generated.proto +++ b/staging/src/k8s.io/api/scheduling/v1beta1/generated.proto @@ -29,6 +29,11 @@ import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; // Package-wide variables from generator "generated". option go_package = "k8s.io/api/scheduling/v1beta1"; +// AllCompositeDisruptionMode means that children of a CompositePodGroup can only be +// disrupted or preempted together. +message AllCompositeDisruptionMode { +} + // AllDisruptionMode specifies that children can only be disrupted together. message AllDisruptionMode { } @@ -43,6 +48,26 @@ message BasicSchedulingPolicy { message CompositeBasicSchedulingPolicy { } +// CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. +// Exactly one mode must be set. +// +// +union +message CompositeDisruptionMode { + // single specifies that children groups can be disrupted independently from each other. + // + // +optional + // +k8s:optional + // +k8s:unionMember + optional SingleCompositeDisruptionMode single = 1; + + // all specifies that all children groups can only be disrupted together. + // + // +optional + // +k8s:optional + // +k8s:unionMember + optional AllCompositeDisruptionMode all = 2; +} + // CompositeGangSchedulingPolicy indicates that the groups belonging to the composite group // should be scheduled using all-or-nothing semantics. message CompositeGangSchedulingPolicy { @@ -109,6 +134,23 @@ message CompositePodGroupTemplate { // +required optional CompositePodGroupSchedulingPolicy schedulingPolicy = 2; + // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. + // This field is immutable. + // + // +optional + // +k8s:optional + // +k8s:immutable + optional CompositePodGroupSchedulingConstraints schedulingConstraints = 3; + + // disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. + // One of Single, All. + // This field is immutable. + // + // +optional + // +k8s:optional + // +k8s:immutable + optional CompositeDisruptionMode disruptionMode = 4; + // priorityClassName indicates the priority that should be considered when scheduling // a composite pod group created from this template. If no priority class is specified, // admission control can set this to the global default priority class if it exists. @@ -120,7 +162,7 @@ message CompositePodGroupTemplate { // +k8s:optional // +k8s:format=k8s-long-name // +k8s:immutable - optional string priorityClassName = 3; + optional string priorityClassName = 5; // priority is the value of priority of composite pod groups created from this template. // Various system components use this field to find the priority of the composite pod group. @@ -133,7 +175,19 @@ message CompositePodGroupTemplate { // +k8s:optional // +k8s:maximum=1000000000 # HighestUserDefinablePriority // +k8s:immutable - optional int32 priority = 4; + optional int32 priority = 6; + + // preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. + // One of Never, PreemptLowerPriority. + // This field is immutable. + // This field is available only when the PodGroupPreemptionPolicy feature gate is enabled. + // + // +featureGate=PodGroupPreemptionPolicy + // +optional + // +k8s:immutable + // +k8s:ifDisabled("PodGroupPreemptionPolicy")=+k8s:forbidden + // +k8s:ifEnabled("PodGroupPreemptionPolicy")=+k8s:optional + optional string preemptionPolicy = 7; // podGroupTemplates is the list of templates for children PodGroups. // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates @@ -148,7 +202,7 @@ message CompositePodGroupTemplate { // +k8s:maxItems=8 // +k8s:update=NoAddItem // +k8s:update=NoRemoveItem - repeated PodGroupTemplate podGroupTemplates = 5; + repeated PodGroupTemplate podGroupTemplates = 8; // compositePodGroupTemplates is the list of templates for children CompositePodGroups. // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates @@ -163,15 +217,7 @@ message CompositePodGroupTemplate { // +k8s:maxItems=8 // +k8s:update=NoAddItem // +k8s:update=NoRemoveItem - repeated CompositePodGroupTemplate compositePodGroupTemplates = 6; - - // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. - // This field is immutable. - // - // +optional - // +k8s:optional - // +k8s:immutable - optional CompositePodGroupSchedulingConstraints schedulingConstraints = 7; + repeated CompositePodGroupTemplate compositePodGroupTemplates = 9; } // DisruptionMode defines how individual entities within a group can be disrupted. @@ -668,6 +714,11 @@ message PriorityClassList { repeated PriorityClass items = 2; } +// SingleCompositeDisruptionMode means that individual children of a CompositePodGroup +// can be disrupted or preempted independently. +message SingleCompositeDisruptionMode { +} + // SingleDisruptionMode specifies that children can be disrupted independently. message SingleDisruptionMode { } diff --git a/staging/src/k8s.io/api/scheduling/v1beta1/types.go b/staging/src/k8s.io/api/scheduling/v1beta1/types.go index 766c6148f9a..6ad22313646 100644 --- a/staging/src/k8s.io/api/scheduling/v1beta1/types.go +++ b/staging/src/k8s.io/api/scheduling/v1beta1/types.go @@ -315,6 +315,23 @@ type CompositePodGroupTemplate struct { // +required SchedulingPolicy CompositePodGroupSchedulingPolicy `json:"schedulingPolicy" protobuf:"bytes,2,opt,name=schedulingPolicy"` + // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. + // This field is immutable. + // + // +optional + // +k8s:optional + // +k8s:immutable + SchedulingConstraints *CompositePodGroupSchedulingConstraints `json:"schedulingConstraints,omitempty" protobuf:"bytes,3,opt,name=schedulingConstraints"` + + // disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. + // One of Single, All. + // This field is immutable. + // + // +optional + // +k8s:optional + // +k8s:immutable + DisruptionMode *CompositeDisruptionMode `json:"disruptionMode,omitempty" protobuf:"bytes,4,opt,name=disruptionMode"` + // priorityClassName indicates the priority that should be considered when scheduling // a composite pod group created from this template. If no priority class is specified, // admission control can set this to the global default priority class if it exists. @@ -326,7 +343,7 @@ type CompositePodGroupTemplate struct { // +k8s:optional // +k8s:format=k8s-long-name // +k8s:immutable - PriorityClassName string `json:"priorityClassName,omitempty" protobuf:"bytes,3,opt,name=priorityClassName"` + PriorityClassName string `json:"priorityClassName,omitempty" protobuf:"bytes,5,opt,name=priorityClassName"` // priority is the value of priority of composite pod groups created from this template. // Various system components use this field to find the priority of the composite pod group. @@ -339,7 +356,19 @@ type CompositePodGroupTemplate struct { // +k8s:optional // +k8s:maximum=1000000000 # HighestUserDefinablePriority // +k8s:immutable - Priority *int32 `json:"priority,omitempty" protobuf:"varint,4,opt,name=priority"` + Priority *int32 `json:"priority,omitempty" protobuf:"varint,6,opt,name=priority"` + + // preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. + // One of Never, PreemptLowerPriority. + // This field is immutable. + // This field is available only when the PodGroupPreemptionPolicy feature gate is enabled. + // + // +featureGate=PodGroupPreemptionPolicy + // +optional + // +k8s:immutable + // +k8s:ifDisabled("PodGroupPreemptionPolicy")=+k8s:forbidden + // +k8s:ifEnabled("PodGroupPreemptionPolicy")=+k8s:optional + PreemptionPolicy *PreemptionPolicy `json:"preemptionPolicy,omitempty" protobuf:"bytes,7,opt,name=preemptionPolicy"` // podGroupTemplates is the list of templates for children PodGroups. // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates @@ -354,7 +383,7 @@ type CompositePodGroupTemplate struct { // +k8s:maxItems=8 // +k8s:update=NoAddItem // +k8s:update=NoRemoveItem - PodGroupTemplates []PodGroupTemplate `json:"podGroupTemplates,omitempty" protobuf:"bytes,5,rep,name=podGroupTemplates"` + PodGroupTemplates []PodGroupTemplate `json:"podGroupTemplates,omitempty" protobuf:"bytes,8,rep,name=podGroupTemplates"` // compositePodGroupTemplates is the list of templates for children CompositePodGroups. // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates @@ -369,15 +398,7 @@ type CompositePodGroupTemplate struct { // +k8s:maxItems=8 // +k8s:update=NoAddItem // +k8s:update=NoRemoveItem - CompositePodGroupTemplates []CompositePodGroupTemplate `json:"compositePodGroupTemplates,omitempty" protobuf:"bytes,6,rep,name=compositePodGroupTemplates"` - - // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. - // This field is immutable. - // - // +optional - // +k8s:optional - // +k8s:immutable - SchedulingConstraints *CompositePodGroupSchedulingConstraints `json:"schedulingConstraints,omitempty" protobuf:"bytes,7,opt,name=schedulingConstraints"` + CompositePodGroupTemplates []CompositePodGroupTemplate `json:"compositePodGroupTemplates,omitempty" protobuf:"bytes,9,rep,name=compositePodGroupTemplates"` } // PodGroupSchedulingPolicy defines the scheduling configuration for a PodGroup. @@ -882,6 +903,38 @@ type CompositeGangSchedulingPolicy struct { MinGroupCount int32 `json:"minGroupCount" protobuf:"varint,1,req,name=minGroupCount"` } +// CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. +// Exactly one mode must be set. +// +// +union +type CompositeDisruptionMode struct { + // single specifies that children groups can be disrupted independently from each other. + // + // +optional + // +k8s:optional + // +k8s:unionMember + Single *SingleCompositeDisruptionMode `json:"single,omitempty" protobuf:"bytes,1,opt,name=single"` + + // all specifies that all children groups can only be disrupted together. + // + // +optional + // +k8s:optional + // +k8s:unionMember + All *AllCompositeDisruptionMode `json:"all,omitempty" protobuf:"bytes,2,opt,name=all"` +} + +// SingleCompositeDisruptionMode means that individual children of a CompositePodGroup +// can be disrupted or preempted independently. +type SingleCompositeDisruptionMode struct { + // This is intentionally empty. +} + +// AllCompositeDisruptionMode means that children of a CompositePodGroup can only be +// disrupted or preempted together. +type AllCompositeDisruptionMode struct { + // This is intentionally empty. +} + // CompositePodGroupSchedulingConstraints defines scheduling constraints (e.g. topology) for a CompositePodGroup. type CompositePodGroupSchedulingConstraints struct { // topology defines the topology constraints for the composite pod group. diff --git a/staging/src/k8s.io/api/scheduling/v1beta1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/scheduling/v1beta1/types_swagger_doc_generated.go index 9c1ba1813b0..57cfb4b010b 100644 --- a/staging/src/k8s.io/api/scheduling/v1beta1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/scheduling/v1beta1/types_swagger_doc_generated.go @@ -27,6 +27,14 @@ package v1beta1 // Those methods can be generated by using hack/update-codegen.sh // AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. +var map_AllCompositeDisruptionMode = map[string]string{ + "": "AllCompositeDisruptionMode means that children of a CompositePodGroup can only be disrupted or preempted together.", +} + +func (AllCompositeDisruptionMode) SwaggerDoc() map[string]string { + return map_AllCompositeDisruptionMode +} + var map_AllDisruptionMode = map[string]string{ "": "AllDisruptionMode specifies that children can only be disrupted together.", } @@ -51,6 +59,16 @@ func (CompositeBasicSchedulingPolicy) SwaggerDoc() map[string]string { return map_CompositeBasicSchedulingPolicy } +var map_CompositeDisruptionMode = map[string]string{ + "": "CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. Exactly one mode must be set.", + "single": "single specifies that children groups can be disrupted independently from each other.", + "all": "all specifies that all children groups can only be disrupted together.", +} + +func (CompositeDisruptionMode) SwaggerDoc() map[string]string { + return map_CompositeDisruptionMode +} + var map_CompositeGangSchedulingPolicy = map[string]string{ "": "CompositeGangSchedulingPolicy indicates that the groups belonging to the composite group should be scheduled using all-or-nothing semantics.", "minGroupCount": "minGroupCount is the minimum number of child groups that must be schedulable or scheduled at the same time for the scheduler to admit the entire group. It must be a positive integer.", @@ -83,11 +101,13 @@ var map_CompositePodGroupTemplate = map[string]string{ "": "CompositePodGroupTemplate represents a template for a CompositePodGroup with a scheduling policy.", "name": "name is a unique identifier for the CompositePodGroupTemplate within the Workload. It must be a DNS label. This field is required.", "schedulingPolicy": "schedulingPolicy defines the scheduling policy for this template.", + "schedulingConstraints": "schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. This field is immutable.", + "disruptionMode": "disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. One of Single, All. This field is immutable.", "priorityClassName": "priorityClassName indicates the priority that should be considered when scheduling a composite pod group created from this template. If no priority class is specified, admission control can set this to the global default priority class if it exists. Otherwise, composite pod groups created from this template will have the priority set to zero. This field is immutable.", "priority": "priority is the value of priority of composite pod groups created from this template. Various system components use this field to find the priority of the composite pod group. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. This field is immutable.", + "preemptionPolicy": "preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. One of Never, PreemptLowerPriority. This field is immutable. This field is available only when the PodGroupPreemptionPolicy feature gate is enabled.", "podGroupTemplates": "podGroupTemplates is the list of templates for children PodGroups. The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates or PodGroupTemplates must be set.", "compositePodGroupTemplates": "compositePodGroupTemplates is the list of templates for children CompositePodGroups. The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates or PodGroupTemplates must be set.", - "schedulingConstraints": "schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. This field is immutable.", } func (CompositePodGroupTemplate) SwaggerDoc() map[string]string { @@ -240,6 +260,14 @@ func (PriorityClassList) SwaggerDoc() map[string]string { return map_PriorityClassList } +var map_SingleCompositeDisruptionMode = map[string]string{ + "": "SingleCompositeDisruptionMode means that individual children of a CompositePodGroup can be disrupted or preempted independently.", +} + +func (SingleCompositeDisruptionMode) SwaggerDoc() map[string]string { + return map_SingleCompositeDisruptionMode +} + var map_SingleDisruptionMode = map[string]string{ "": "SingleDisruptionMode specifies that children can be disrupted independently.", } diff --git a/staging/src/k8s.io/api/scheduling/v1beta1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/scheduling/v1beta1/zz_generated.deepcopy.go index 7bd5c754ed1..aacc643ad02 100644 --- a/staging/src/k8s.io/api/scheduling/v1beta1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/scheduling/v1beta1/zz_generated.deepcopy.go @@ -27,6 +27,22 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AllCompositeDisruptionMode) DeepCopyInto(out *AllCompositeDisruptionMode) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllCompositeDisruptionMode. +func (in *AllCompositeDisruptionMode) DeepCopy() *AllCompositeDisruptionMode { + if in == nil { + return nil + } + out := new(AllCompositeDisruptionMode) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AllDisruptionMode) DeepCopyInto(out *AllDisruptionMode) { *out = *in @@ -75,6 +91,32 @@ func (in *CompositeBasicSchedulingPolicy) DeepCopy() *CompositeBasicSchedulingPo return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CompositeDisruptionMode) DeepCopyInto(out *CompositeDisruptionMode) { + *out = *in + if in.Single != nil { + in, out := &in.Single, &out.Single + *out = new(SingleCompositeDisruptionMode) + **out = **in + } + if in.All != nil { + in, out := &in.All, &out.All + *out = new(AllCompositeDisruptionMode) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CompositeDisruptionMode. +func (in *CompositeDisruptionMode) DeepCopy() *CompositeDisruptionMode { + if in == nil { + return nil + } + out := new(CompositeDisruptionMode) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CompositeGangSchedulingPolicy) DeepCopyInto(out *CompositeGangSchedulingPolicy) { *out = *in @@ -142,11 +184,26 @@ func (in *CompositePodGroupSchedulingPolicy) DeepCopy() *CompositePodGroupSchedu func (in *CompositePodGroupTemplate) DeepCopyInto(out *CompositePodGroupTemplate) { *out = *in in.SchedulingPolicy.DeepCopyInto(&out.SchedulingPolicy) + if in.SchedulingConstraints != nil { + in, out := &in.SchedulingConstraints, &out.SchedulingConstraints + *out = new(CompositePodGroupSchedulingConstraints) + (*in).DeepCopyInto(*out) + } + if in.DisruptionMode != nil { + in, out := &in.DisruptionMode, &out.DisruptionMode + *out = new(CompositeDisruptionMode) + (*in).DeepCopyInto(*out) + } if in.Priority != nil { in, out := &in.Priority, &out.Priority *out = new(int32) **out = **in } + if in.PreemptionPolicy != nil { + in, out := &in.PreemptionPolicy, &out.PreemptionPolicy + *out = new(PreemptionPolicy) + **out = **in + } if in.PodGroupTemplates != nil { in, out := &in.PodGroupTemplates, &out.PodGroupTemplates *out = make([]PodGroupTemplate, len(*in)) @@ -161,11 +218,6 @@ func (in *CompositePodGroupTemplate) DeepCopyInto(out *CompositePodGroupTemplate (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.SchedulingConstraints != nil { - in, out := &in.SchedulingConstraints, &out.SchedulingConstraints - *out = new(CompositePodGroupSchedulingConstraints) - (*in).DeepCopyInto(*out) - } return } @@ -568,6 +620,22 @@ func (in *PriorityClassList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SingleCompositeDisruptionMode) DeepCopyInto(out *SingleCompositeDisruptionMode) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SingleCompositeDisruptionMode. +func (in *SingleCompositeDisruptionMode) DeepCopy() *SingleCompositeDisruptionMode { + if in == nil { + return nil + } + out := new(SingleCompositeDisruptionMode) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SingleDisruptionMode) DeepCopyInto(out *SingleDisruptionMode) { *out = *in diff --git a/staging/src/k8s.io/api/scheduling/v1beta1/zz_generated.model_name.go b/staging/src/k8s.io/api/scheduling/v1beta1/zz_generated.model_name.go index 7f69a3db577..be01a4c3ebe 100644 --- a/staging/src/k8s.io/api/scheduling/v1beta1/zz_generated.model_name.go +++ b/staging/src/k8s.io/api/scheduling/v1beta1/zz_generated.model_name.go @@ -21,6 +21,11 @@ limitations under the License. package v1beta1 +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in AllCompositeDisruptionMode) OpenAPIModelName() string { + return "io.k8s.api.scheduling.v1beta1.AllCompositeDisruptionMode" +} + // OpenAPIModelName returns the OpenAPI model name for this type. func (in AllDisruptionMode) OpenAPIModelName() string { return "io.k8s.api.scheduling.v1beta1.AllDisruptionMode" @@ -36,6 +41,11 @@ func (in CompositeBasicSchedulingPolicy) OpenAPIModelName() string { return "io.k8s.api.scheduling.v1beta1.CompositeBasicSchedulingPolicy" } +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in CompositeDisruptionMode) OpenAPIModelName() string { + return "io.k8s.api.scheduling.v1beta1.CompositeDisruptionMode" +} + // OpenAPIModelName returns the OpenAPI model name for this type. func (in CompositeGangSchedulingPolicy) OpenAPIModelName() string { return "io.k8s.api.scheduling.v1beta1.CompositeGangSchedulingPolicy" @@ -121,6 +131,11 @@ func (in PriorityClassList) OpenAPIModelName() string { return "io.k8s.api.scheduling.v1beta1.PriorityClassList" } +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in SingleCompositeDisruptionMode) OpenAPIModelName() string { + return "io.k8s.api.scheduling.v1beta1.SingleCompositeDisruptionMode" +} + // OpenAPIModelName returns the OpenAPI model name for this type. func (in SingleDisruptionMode) OpenAPIModelName() string { return "io.k8s.api.scheduling.v1beta1.SingleDisruptionMode" diff --git a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.CompositePodGroup.json b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.CompositePodGroup.json index a02a0f758df..c5e3a39f606 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.CompositePodGroup.json +++ b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.CompositePodGroup.json @@ -55,15 +55,20 @@ "minGroupCount": 1 } }, - "priorityClassName": "priorityClassNameValue", - "priority": 5, "schedulingConstraints": { "topology": [ { "key": "keyValue" } ] - } + }, + "disruptionMode": { + "single": {}, + "all": {} + }, + "priorityClassName": "priorityClassNameValue", + "priority": 7, + "preemptionPolicy": "preemptionPolicyValue" }, "status": { "conditions": [ diff --git a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.CompositePodGroup.pb b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.CompositePodGroup.pb index 5ab421106c6..723dd3ae074 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.CompositePodGroup.pb and b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.CompositePodGroup.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.CompositePodGroup.yaml b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.CompositePodGroup.yaml index dcd1e437b3d..fd038f04800 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.CompositePodGroup.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.CompositePodGroup.yaml @@ -33,8 +33,12 @@ metadata: selfLink: selfLinkValue uid: uidValue spec: + disruptionMode: + all: {} + single: {} parentCompositePodGroupName: parentCompositePodGroupNameValue - priority: 5 + preemptionPolicy: preemptionPolicyValue + priority: 7 priorityClassName: priorityClassNameValue schedulingConstraints: topology: diff --git a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.Workload.json b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.Workload.json index df46c6e04f1..6541522a092 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.Workload.json +++ b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.Workload.json @@ -90,8 +90,20 @@ "minGroupCount": 1 } }, + "schedulingConstraints": { + "topology": [ + { + "key": "keyValue" + } + ] + }, + "disruptionMode": { + "single": {}, + "all": {} + }, "priorityClassName": "priorityClassNameValue", - "priority": 4, + "priority": 6, + "preemptionPolicy": "preemptionPolicyValue", "podGroupTemplates": [ { "name": "nameValue", @@ -123,14 +135,7 @@ "priority": 7, "preemptionPolicy": "preemptionPolicyValue" } - ], - "schedulingConstraints": { - "topology": [ - { - "key": "keyValue" - } - ] - } + ] } ] } diff --git a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.Workload.pb b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.Workload.pb index 19f47f6193e..69207188326 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.Workload.pb and b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.Workload.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.Workload.yaml b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.Workload.yaml index 8c383aecd94..8257753db8f 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.Workload.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1alpha3.Workload.yaml @@ -34,7 +34,10 @@ metadata: uid: uidValue spec: compositePodGroupTemplates: - - name: nameValue + - disruptionMode: + all: {} + single: {} + name: nameValue podGroupTemplates: - disruptionMode: all: {} @@ -54,7 +57,8 @@ spec: basic: {} gang: minCount: 1 - priority: 4 + preemptionPolicy: preemptionPolicyValue + priority: 6 priorityClassName: priorityClassNameValue schedulingConstraints: topology: diff --git a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1beta1.Workload.json b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1beta1.Workload.json index e99c8f3d956..f92742c8688 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1beta1.Workload.json +++ b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1beta1.Workload.json @@ -90,8 +90,20 @@ "minGroupCount": 1 } }, + "schedulingConstraints": { + "topology": [ + { + "key": "keyValue" + } + ] + }, + "disruptionMode": { + "single": {}, + "all": {} + }, "priorityClassName": "priorityClassNameValue", - "priority": 4, + "priority": 6, + "preemptionPolicy": "preemptionPolicyValue", "podGroupTemplates": [ { "name": "nameValue", @@ -123,14 +135,7 @@ "priority": 7, "preemptionPolicy": "preemptionPolicyValue" } - ], - "schedulingConstraints": { - "topology": [ - { - "key": "keyValue" - } - ] - } + ] } ] } diff --git a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1beta1.Workload.pb b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1beta1.Workload.pb index 248d00740e9..09a911cb46c 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1beta1.Workload.pb and b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1beta1.Workload.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1beta1.Workload.yaml b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1beta1.Workload.yaml index 0036bfcc320..19feb5e67e8 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1beta1.Workload.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/scheduling.k8s.io.v1beta1.Workload.yaml @@ -34,7 +34,10 @@ metadata: uid: uidValue spec: compositePodGroupTemplates: - - name: nameValue + - disruptionMode: + all: {} + single: {} + name: nameValue podGroupTemplates: - disruptionMode: all: {} @@ -54,7 +57,8 @@ spec: basic: {} gang: minCount: 1 - priority: 4 + preemptionPolicy: preemptionPolicyValue + priority: 6 priorityClassName: priorityClassNameValue schedulingConstraints: topology: diff --git a/staging/src/k8s.io/client-go/applyconfigurations/internal/internal.go b/staging/src/k8s.io/client-go/applyconfigurations/internal/internal.go index 016dcff0eab..6a6b9dfec87 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/internal/internal.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/internal/internal.go @@ -14947,6 +14947,18 @@ var schemaYAML = typed.YAMLObject(`types: type: scalar: numeric default: 0 +- name: io.k8s.api.scheduling.v1alpha3.AllCompositeDisruptionMode + map: + elementType: + scalar: untyped + list: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic + map: + elementType: + namedType: __untyped_deduced_ + elementRelationship: separable - name: io.k8s.api.scheduling.v1alpha3.AllDisruptionMode map: elementType: @@ -14983,6 +14995,21 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: __untyped_deduced_ elementRelationship: separable +- name: io.k8s.api.scheduling.v1alpha3.CompositeDisruptionMode + map: + fields: + - name: all + type: + namedType: io.k8s.api.scheduling.v1alpha3.AllCompositeDisruptionMode + - name: single + type: + namedType: io.k8s.api.scheduling.v1alpha3.SingleCompositeDisruptionMode + unions: + - fields: + - fieldName: all + discriminatorValue: All + - fieldName: single + discriminatorValue: Single - name: io.k8s.api.scheduling.v1alpha3.CompositeGangSchedulingPolicy map: fields: @@ -15038,9 +15065,17 @@ var schemaYAML = typed.YAMLObject(`types: - name: io.k8s.api.scheduling.v1alpha3.CompositePodGroupSpec map: fields: + - name: disruptionMode + type: + namedType: io.k8s.api.scheduling.v1alpha3.CompositeDisruptionMode + default: + single: {} - name: parentCompositePodGroupName type: scalar: string + - name: preemptionPolicy + type: + scalar: string - name: priority type: scalar: numeric @@ -15079,6 +15114,9 @@ var schemaYAML = typed.YAMLObject(`types: elementRelationship: associative keys: - name + - name: disruptionMode + type: + namedType: io.k8s.api.scheduling.v1alpha3.CompositeDisruptionMode - name: name type: scalar: string @@ -15091,6 +15129,9 @@ var schemaYAML = typed.YAMLObject(`types: elementRelationship: associative keys: - name + - name: preemptionPolicy + type: + scalar: string - name: priority type: scalar: numeric @@ -15285,6 +15326,18 @@ var schemaYAML = typed.YAMLObject(`types: type: namedType: io.k8s.api.scheduling.v1alpha3.PodGroupSchedulingPolicy default: {} +- name: io.k8s.api.scheduling.v1alpha3.SingleCompositeDisruptionMode + map: + elementType: + scalar: untyped + list: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic + map: + elementType: + namedType: __untyped_deduced_ + elementRelationship: separable - name: io.k8s.api.scheduling.v1alpha3.SingleDisruptionMode map: elementType: @@ -15462,6 +15515,18 @@ var schemaYAML = typed.YAMLObject(`types: elementRelationship: associative keys: - name +- name: io.k8s.api.scheduling.v1beta1.AllCompositeDisruptionMode + map: + elementType: + scalar: untyped + list: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic + map: + elementType: + namedType: __untyped_deduced_ + elementRelationship: separable - name: io.k8s.api.scheduling.v1beta1.AllDisruptionMode map: elementType: @@ -15498,6 +15563,21 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: __untyped_deduced_ elementRelationship: separable +- name: io.k8s.api.scheduling.v1beta1.CompositeDisruptionMode + map: + fields: + - name: all + type: + namedType: io.k8s.api.scheduling.v1beta1.AllCompositeDisruptionMode + - name: single + type: + namedType: io.k8s.api.scheduling.v1beta1.SingleCompositeDisruptionMode + unions: + - fields: + - fieldName: all + discriminatorValue: All + - fieldName: single + discriminatorValue: Single - name: io.k8s.api.scheduling.v1beta1.CompositeGangSchedulingPolicy map: fields: @@ -15540,6 +15620,9 @@ var schemaYAML = typed.YAMLObject(`types: elementRelationship: associative keys: - name + - name: disruptionMode + type: + namedType: io.k8s.api.scheduling.v1beta1.CompositeDisruptionMode - name: name type: scalar: string @@ -15552,6 +15635,9 @@ var schemaYAML = typed.YAMLObject(`types: elementRelationship: associative keys: - name + - name: preemptionPolicy + type: + scalar: string - name: priority type: scalar: numeric @@ -15772,6 +15858,18 @@ var schemaYAML = typed.YAMLObject(`types: type: scalar: numeric default: 0 +- name: io.k8s.api.scheduling.v1beta1.SingleCompositeDisruptionMode + map: + elementType: + scalar: untyped + list: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic + map: + elementType: + namedType: __untyped_deduced_ + elementRelationship: separable - name: io.k8s.api.scheduling.v1beta1.SingleDisruptionMode map: elementType: diff --git a/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1alpha3/compositedisruptionmode.go b/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1alpha3/compositedisruptionmode.go new file mode 100644 index 00000000000..70ff0162ace --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1alpha3/compositedisruptionmode.go @@ -0,0 +1,57 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha3 + +import ( + schedulingv1alpha3 "k8s.io/api/scheduling/v1alpha3" +) + +// CompositeDisruptionModeApplyConfiguration represents a declarative configuration of the CompositeDisruptionMode type for use +// with apply. +// +// CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. +// Exactly one mode must be set. +type CompositeDisruptionModeApplyConfiguration struct { + // single specifies that children groups can be disrupted independently from each other. + Single *schedulingv1alpha3.SingleCompositeDisruptionMode `json:"single,omitempty"` + // all specifies that all children groups can only be disrupted together. + All *schedulingv1alpha3.AllCompositeDisruptionMode `json:"all,omitempty"` +} + +// CompositeDisruptionModeApplyConfiguration constructs a declarative configuration of the CompositeDisruptionMode type for use with +// apply. +func CompositeDisruptionMode() *CompositeDisruptionModeApplyConfiguration { + return &CompositeDisruptionModeApplyConfiguration{} +} + +// WithSingle sets the Single 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 Single field is set to the value of the last call. +func (b *CompositeDisruptionModeApplyConfiguration) WithSingle(value schedulingv1alpha3.SingleCompositeDisruptionMode) *CompositeDisruptionModeApplyConfiguration { + b.Single = &value + return b +} + +// WithAll sets the All 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 All field is set to the value of the last call. +func (b *CompositeDisruptionModeApplyConfiguration) WithAll(value schedulingv1alpha3.AllCompositeDisruptionMode) *CompositeDisruptionModeApplyConfiguration { + b.All = &value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1alpha3/compositepodgroupspec.go b/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1alpha3/compositepodgroupspec.go index d2d74b3b3c8..16bc538a542 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1alpha3/compositepodgroupspec.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1alpha3/compositepodgroupspec.go @@ -18,6 +18,10 @@ limitations under the License. package v1alpha3 +import ( + schedulingv1alpha3 "k8s.io/api/scheduling/v1alpha3" +) + // CompositePodGroupSpecApplyConfiguration represents a declarative configuration of the CompositePodGroupSpec type for use // with apply. // @@ -37,6 +41,15 @@ type CompositePodGroupSpecApplyConfiguration struct { // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. // This field is immutable. SchedulingPolicy *CompositePodGroupSchedulingPolicyApplyConfiguration `json:"schedulingPolicy,omitempty"` + // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroup. + // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. + // This field is immutable. + SchedulingConstraints *CompositePodGroupSchedulingConstraintsApplyConfiguration `json:"schedulingConstraints,omitempty"` + // disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. + // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. + // One of Single, All. Defaults to Single if unset. + // This field is immutable. + DisruptionMode *CompositeDisruptionModeApplyConfiguration `json:"disruptionMode,omitempty"` // priorityClassName defines the priority that should be considered when scheduling this CompositePodGroup. // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. // If left unspecified, it is validated and resolved similarly to the PriorityClassName field in Pods @@ -51,10 +64,13 @@ type CompositePodGroupSpecApplyConfiguration struct { // The higher the value, the higher the priority. // This field is immutable. Priority *int32 `json:"priority,omitempty"` - // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroup. - // Controllers are expected to fill this field by copying it from a CompositePodGroupTemplate. + // preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. + // One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. + // When Priority Admission Controller is enabled, it populates this field from PriorityClassName, + // and defaults to PreemptLowerPriority if value is unset in PriorityClass. // This field is immutable. - SchedulingConstraints *CompositePodGroupSchedulingConstraintsApplyConfiguration `json:"schedulingConstraints,omitempty"` + // This field is available only when the PodGroupPreemptionPolicy feature gate is enabled. + PreemptionPolicy *schedulingv1alpha3.PreemptionPolicy `json:"preemptionPolicy,omitempty"` } // CompositePodGroupSpecApplyConfiguration constructs a declarative configuration of the CompositePodGroupSpec type for use with @@ -87,6 +103,22 @@ func (b *CompositePodGroupSpecApplyConfiguration) WithSchedulingPolicy(value *Co return b } +// WithSchedulingConstraints sets the SchedulingConstraints 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 SchedulingConstraints field is set to the value of the last call. +func (b *CompositePodGroupSpecApplyConfiguration) WithSchedulingConstraints(value *CompositePodGroupSchedulingConstraintsApplyConfiguration) *CompositePodGroupSpecApplyConfiguration { + b.SchedulingConstraints = value + return b +} + +// WithDisruptionMode sets the DisruptionMode 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 DisruptionMode field is set to the value of the last call. +func (b *CompositePodGroupSpecApplyConfiguration) WithDisruptionMode(value *CompositeDisruptionModeApplyConfiguration) *CompositePodGroupSpecApplyConfiguration { + b.DisruptionMode = value + return b +} + // WithPriorityClassName sets the PriorityClassName 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 PriorityClassName field is set to the value of the last call. @@ -103,10 +135,10 @@ func (b *CompositePodGroupSpecApplyConfiguration) WithPriority(value int32) *Com return b } -// WithSchedulingConstraints sets the SchedulingConstraints field in the declarative configuration to the given value +// WithPreemptionPolicy sets the PreemptionPolicy 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 SchedulingConstraints field is set to the value of the last call. -func (b *CompositePodGroupSpecApplyConfiguration) WithSchedulingConstraints(value *CompositePodGroupSchedulingConstraintsApplyConfiguration) *CompositePodGroupSpecApplyConfiguration { - b.SchedulingConstraints = value +// If called multiple times, the PreemptionPolicy field is set to the value of the last call. +func (b *CompositePodGroupSpecApplyConfiguration) WithPreemptionPolicy(value schedulingv1alpha3.PreemptionPolicy) *CompositePodGroupSpecApplyConfiguration { + b.PreemptionPolicy = &value return b } diff --git a/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1alpha3/compositepodgrouptemplate.go b/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1alpha3/compositepodgrouptemplate.go index 96925f1a454..fd8aadc2edd 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1alpha3/compositepodgrouptemplate.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1alpha3/compositepodgrouptemplate.go @@ -18,6 +18,10 @@ limitations under the License. package v1alpha3 +import ( + schedulingv1alpha3 "k8s.io/api/scheduling/v1alpha3" +) + // CompositePodGroupTemplateApplyConfiguration represents a declarative configuration of the CompositePodGroupTemplate type for use // with apply. // @@ -28,6 +32,13 @@ type CompositePodGroupTemplateApplyConfiguration struct { Name *string `json:"name,omitempty"` // schedulingPolicy defines the scheduling policy for this template. SchedulingPolicy *CompositePodGroupSchedulingPolicyApplyConfiguration `json:"schedulingPolicy,omitempty"` + // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. + // This field is immutable. + SchedulingConstraints *CompositePodGroupSchedulingConstraintsApplyConfiguration `json:"schedulingConstraints,omitempty"` + // disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. + // One of Single, All. + // This field is immutable. + DisruptionMode *CompositeDisruptionModeApplyConfiguration `json:"disruptionMode,omitempty"` // priorityClassName indicates the priority that should be considered when scheduling // a composite pod group created from this template. If no priority class is specified, // admission control can set this to the global default priority class if it exists. @@ -42,6 +53,11 @@ type CompositePodGroupTemplateApplyConfiguration struct { // The higher the value, the higher the priority. // This field is immutable. Priority *int32 `json:"priority,omitempty"` + // preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. + // One of Never, PreemptLowerPriority. + // This field is immutable. + // This field is available only when the PodGroupPreemptionPolicy feature gate is enabled. + PreemptionPolicy *schedulingv1alpha3.PreemptionPolicy `json:"preemptionPolicy,omitempty"` // podGroupTemplates is the list of templates for children PodGroups. // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates // or PodGroupTemplates must be set. @@ -50,9 +66,6 @@ type CompositePodGroupTemplateApplyConfiguration struct { // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates // or PodGroupTemplates must be set. CompositePodGroupTemplates []CompositePodGroupTemplateApplyConfiguration `json:"compositePodGroupTemplates,omitempty"` - // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. - // This field is immutable. - SchedulingConstraints *CompositePodGroupSchedulingConstraintsApplyConfiguration `json:"schedulingConstraints,omitempty"` } // CompositePodGroupTemplateApplyConfiguration constructs a declarative configuration of the CompositePodGroupTemplate type for use with @@ -77,6 +90,22 @@ func (b *CompositePodGroupTemplateApplyConfiguration) WithSchedulingPolicy(value return b } +// WithSchedulingConstraints sets the SchedulingConstraints 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 SchedulingConstraints field is set to the value of the last call. +func (b *CompositePodGroupTemplateApplyConfiguration) WithSchedulingConstraints(value *CompositePodGroupSchedulingConstraintsApplyConfiguration) *CompositePodGroupTemplateApplyConfiguration { + b.SchedulingConstraints = value + return b +} + +// WithDisruptionMode sets the DisruptionMode 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 DisruptionMode field is set to the value of the last call. +func (b *CompositePodGroupTemplateApplyConfiguration) WithDisruptionMode(value *CompositeDisruptionModeApplyConfiguration) *CompositePodGroupTemplateApplyConfiguration { + b.DisruptionMode = value + return b +} + // WithPriorityClassName sets the PriorityClassName 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 PriorityClassName field is set to the value of the last call. @@ -93,6 +122,14 @@ func (b *CompositePodGroupTemplateApplyConfiguration) WithPriority(value int32) return b } +// WithPreemptionPolicy sets the PreemptionPolicy 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 PreemptionPolicy field is set to the value of the last call. +func (b *CompositePodGroupTemplateApplyConfiguration) WithPreemptionPolicy(value schedulingv1alpha3.PreemptionPolicy) *CompositePodGroupTemplateApplyConfiguration { + b.PreemptionPolicy = &value + return b +} + // WithPodGroupTemplates adds the given value to the PodGroupTemplates 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 PodGroupTemplates field. @@ -118,11 +155,3 @@ func (b *CompositePodGroupTemplateApplyConfiguration) WithCompositePodGroupTempl } return b } - -// WithSchedulingConstraints sets the SchedulingConstraints 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 SchedulingConstraints field is set to the value of the last call. -func (b *CompositePodGroupTemplateApplyConfiguration) WithSchedulingConstraints(value *CompositePodGroupSchedulingConstraintsApplyConfiguration) *CompositePodGroupTemplateApplyConfiguration { - b.SchedulingConstraints = value - return b -} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1beta1/compositedisruptionmode.go b/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1beta1/compositedisruptionmode.go new file mode 100644 index 00000000000..40f9a629847 --- /dev/null +++ b/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1beta1/compositedisruptionmode.go @@ -0,0 +1,57 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1beta1 + +import ( + schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" +) + +// CompositeDisruptionModeApplyConfiguration represents a declarative configuration of the CompositeDisruptionMode type for use +// with apply. +// +// CompositeDisruptionMode defines how individual entities within a composite pod group can be disrupted. +// Exactly one mode must be set. +type CompositeDisruptionModeApplyConfiguration struct { + // single specifies that children groups can be disrupted independently from each other. + Single *schedulingv1beta1.SingleCompositeDisruptionMode `json:"single,omitempty"` + // all specifies that all children groups can only be disrupted together. + All *schedulingv1beta1.AllCompositeDisruptionMode `json:"all,omitempty"` +} + +// CompositeDisruptionModeApplyConfiguration constructs a declarative configuration of the CompositeDisruptionMode type for use with +// apply. +func CompositeDisruptionMode() *CompositeDisruptionModeApplyConfiguration { + return &CompositeDisruptionModeApplyConfiguration{} +} + +// WithSingle sets the Single 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 Single field is set to the value of the last call. +func (b *CompositeDisruptionModeApplyConfiguration) WithSingle(value schedulingv1beta1.SingleCompositeDisruptionMode) *CompositeDisruptionModeApplyConfiguration { + b.Single = &value + return b +} + +// WithAll sets the All 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 All field is set to the value of the last call. +func (b *CompositeDisruptionModeApplyConfiguration) WithAll(value schedulingv1beta1.AllCompositeDisruptionMode) *CompositeDisruptionModeApplyConfiguration { + b.All = &value + return b +} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1beta1/compositepodgrouptemplate.go b/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1beta1/compositepodgrouptemplate.go index 17ed08d242a..511b4cca547 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1beta1/compositepodgrouptemplate.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/scheduling/v1beta1/compositepodgrouptemplate.go @@ -18,6 +18,10 @@ limitations under the License. package v1beta1 +import ( + schedulingv1beta1 "k8s.io/api/scheduling/v1beta1" +) + // CompositePodGroupTemplateApplyConfiguration represents a declarative configuration of the CompositePodGroupTemplate type for use // with apply. // @@ -28,6 +32,13 @@ type CompositePodGroupTemplateApplyConfiguration struct { Name *string `json:"name,omitempty"` // schedulingPolicy defines the scheduling policy for this template. SchedulingPolicy *CompositePodGroupSchedulingPolicyApplyConfiguration `json:"schedulingPolicy,omitempty"` + // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. + // This field is immutable. + SchedulingConstraints *CompositePodGroupSchedulingConstraintsApplyConfiguration `json:"schedulingConstraints,omitempty"` + // disruptionMode defines the mode in which a given CompositePodGroup can be disrupted. + // One of Single, All. + // This field is immutable. + DisruptionMode *CompositeDisruptionModeApplyConfiguration `json:"disruptionMode,omitempty"` // priorityClassName indicates the priority that should be considered when scheduling // a composite pod group created from this template. If no priority class is specified, // admission control can set this to the global default priority class if it exists. @@ -42,6 +53,11 @@ type CompositePodGroupTemplateApplyConfiguration struct { // The higher the value, the higher the priority. // This field is immutable. Priority *int32 `json:"priority,omitempty"` + // preemptionPolicy is the Policy for preempting pods/podgroups with lower priority. + // One of Never, PreemptLowerPriority. + // This field is immutable. + // This field is available only when the PodGroupPreemptionPolicy feature gate is enabled. + PreemptionPolicy *schedulingv1beta1.PreemptionPolicy `json:"preemptionPolicy,omitempty"` // podGroupTemplates is the list of templates for children PodGroups. // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates // or PodGroupTemplates must be set. @@ -50,9 +66,6 @@ type CompositePodGroupTemplateApplyConfiguration struct { // The maximum number of templates is 8. At least one entry in CompositePodGroupTemplates // or PodGroupTemplates must be set. CompositePodGroupTemplates []CompositePodGroupTemplateApplyConfiguration `json:"compositePodGroupTemplates,omitempty"` - // schedulingConstraints defines optional scheduling constraints (e.g. topology) for this CompositePodGroupTemplate. - // This field is immutable. - SchedulingConstraints *CompositePodGroupSchedulingConstraintsApplyConfiguration `json:"schedulingConstraints,omitempty"` } // CompositePodGroupTemplateApplyConfiguration constructs a declarative configuration of the CompositePodGroupTemplate type for use with @@ -77,6 +90,22 @@ func (b *CompositePodGroupTemplateApplyConfiguration) WithSchedulingPolicy(value return b } +// WithSchedulingConstraints sets the SchedulingConstraints 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 SchedulingConstraints field is set to the value of the last call. +func (b *CompositePodGroupTemplateApplyConfiguration) WithSchedulingConstraints(value *CompositePodGroupSchedulingConstraintsApplyConfiguration) *CompositePodGroupTemplateApplyConfiguration { + b.SchedulingConstraints = value + return b +} + +// WithDisruptionMode sets the DisruptionMode 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 DisruptionMode field is set to the value of the last call. +func (b *CompositePodGroupTemplateApplyConfiguration) WithDisruptionMode(value *CompositeDisruptionModeApplyConfiguration) *CompositePodGroupTemplateApplyConfiguration { + b.DisruptionMode = value + return b +} + // WithPriorityClassName sets the PriorityClassName 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 PriorityClassName field is set to the value of the last call. @@ -93,6 +122,14 @@ func (b *CompositePodGroupTemplateApplyConfiguration) WithPriority(value int32) return b } +// WithPreemptionPolicy sets the PreemptionPolicy 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 PreemptionPolicy field is set to the value of the last call. +func (b *CompositePodGroupTemplateApplyConfiguration) WithPreemptionPolicy(value schedulingv1beta1.PreemptionPolicy) *CompositePodGroupTemplateApplyConfiguration { + b.PreemptionPolicy = &value + return b +} + // WithPodGroupTemplates adds the given value to the PodGroupTemplates 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 PodGroupTemplates field. @@ -118,11 +155,3 @@ func (b *CompositePodGroupTemplateApplyConfiguration) WithCompositePodGroupTempl } return b } - -// WithSchedulingConstraints sets the SchedulingConstraints 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 SchedulingConstraints field is set to the value of the last call. -func (b *CompositePodGroupTemplateApplyConfiguration) WithSchedulingConstraints(value *CompositePodGroupSchedulingConstraintsApplyConfiguration) *CompositePodGroupTemplateApplyConfiguration { - b.SchedulingConstraints = value - return b -} diff --git a/staging/src/k8s.io/client-go/applyconfigurations/utils.go b/staging/src/k8s.io/client-go/applyconfigurations/utils.go index 0bdddf1f649..6362d41bf4c 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/utils.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/utils.go @@ -1866,6 +1866,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &applyconfigurationsschedulingv1.PriorityClassApplyConfiguration{} // Group=scheduling.k8s.io, Version=v1alpha3 + case schedulingv1alpha3.SchemeGroupVersion.WithKind("CompositeDisruptionMode"): + return &applyconfigurationsschedulingv1alpha3.CompositeDisruptionModeApplyConfiguration{} case schedulingv1alpha3.SchemeGroupVersion.WithKind("CompositeGangSchedulingPolicy"): return &applyconfigurationsschedulingv1alpha3.CompositeGangSchedulingPolicyApplyConfiguration{} case schedulingv1alpha3.SchemeGroupVersion.WithKind("CompositePodGroup"): @@ -1922,6 +1924,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &applyconfigurationsschedulingv1alpha3.WorkloadSpecApplyConfiguration{} // Group=scheduling.k8s.io, Version=v1beta1 + case schedulingv1beta1.SchemeGroupVersion.WithKind("CompositeDisruptionMode"): + return &applyconfigurationsschedulingv1beta1.CompositeDisruptionModeApplyConfiguration{} case schedulingv1beta1.SchemeGroupVersion.WithKind("CompositeGangSchedulingPolicy"): return &applyconfigurationsschedulingv1beta1.CompositeGangSchedulingPolicyApplyConfiguration{} case schedulingv1beta1.SchemeGroupVersion.WithKind("CompositePodGroupSchedulingConstraints"): diff --git a/test/declarative_validation/scheduling/compositepodgroup/declarative_validation_test.go b/test/declarative_validation/scheduling/compositepodgroup/declarative_validation_test.go index c7e3f1ef0d5..7bff8528060 100644 --- a/test/declarative_validation/scheduling/compositepodgroup/declarative_validation_test.go +++ b/test/declarative_validation/scheduling/compositepodgroup/declarative_validation_test.go @@ -56,8 +56,9 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) { strategy := registry.NewStrategy() testCases := map[string]struct { - input scheduling.CompositePodGroup - expectedErrs field.ErrorList + input scheduling.CompositePodGroup + enablePodGroupPreemptionPolicy bool + expectedErrs field.ErrorList }{ "valid": { input: mkValidCompositePodGroup(), @@ -142,6 +143,40 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) { input: mkValidCompositePodGroup(addTopologyConstraint("Example.com/Foo")), expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "schedulingConstraints", "topology").Index(0).Child("key"), nil, "").WithOrigin("format=k8s-label-key")}, }, + "composite pod group disruption mode all": { + input: mkValidCompositePodGroup(setDisruptionModeAll()), + }, + "disruption mode with neither single nor all": { + input: mkValidCompositePodGroup(setDisruptionModeNeither()), + expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "disruptionMode"), nil, "").WithOrigin("union")}, + }, + "disruption mode with both single and all": { + input: mkValidCompositePodGroup(setDisruptionModeBoth()), + expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "disruptionMode"), nil, "").WithOrigin("union")}, + }, + "composite pod group without disruption mode": { + input: mkValidCompositePodGroup(clearDisruptionMode()), + expectedErrs: field.ErrorList{field.Required(field.NewPath("spec", "disruptionMode"), "")}, + }, + "preemption policy set, PodGroupPreemptionPolicy disabled": { + input: mkValidCompositePodGroup(setPreemptionPolicy(scheduling.PreemptNever)), + expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec", "preemptionPolicy"), "")}, + }, + "valid preemption policy (Never), PodGroupPreemptionPolicy enabled": { + input: mkValidCompositePodGroup(setPreemptionPolicy(scheduling.PreemptNever)), + enablePodGroupPreemptionPolicy: true, + }, + "invalid preemption policy, PodGroupPreemptionPolicy enabled": { + input: mkValidCompositePodGroup(setPreemptionPolicy(scheduling.PreemptionPolicy("Invalid"))), + enablePodGroupPreemptionPolicy: true, + expectedErrs: field.ErrorList{ + field.NotSupported(field.NewPath("spec", "preemptionPolicy"), scheduling.PreemptionPolicy("Invalid"), []string{"Never", "PreemptLowerPriority"}), + }, + }, + "composite pod group without preemption policy, PodGroupPreemptionPolicy enabled": { + input: mkValidCompositePodGroup(clearPreemptionPolicy()), + enablePodGroupPreemptionPolicy: true, + }, } for k, tc := range testCases { @@ -150,6 +185,7 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) { features.GenericWorkload: true, features.CompositePodGroup: true, features.TopologyAwareWorkloadScheduling: true, + features.PodGroupPreemptionPolicy: tc.enablePodGroupPreemptionPolicy, }) apitesting.VerifyValidationEquivalence(t, ctx, &tc.input, strategy, tc.expectedErrs) }) @@ -179,9 +215,10 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) { }) testCases := map[string]struct { - oldObj scheduling.CompositePodGroup - updateObj scheduling.CompositePodGroup - expectedErrs field.ErrorList + oldObj scheduling.CompositePodGroup + updateObj scheduling.CompositePodGroup + enablePodGroupPreemptionPolicy bool + expectedErrs field.ErrorList }{ "valid update": { oldObj: mkValidCompositePodGroup(setResourceVersion("1")), @@ -256,6 +293,38 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) { updateObj: mkValidCompositePodGroup(setResourceVersion("1"), addTopologyConstraint("bar")), expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "schedulingConstraints"), nil, "field is immutable").WithOrigin("immutable")}, }, + "invalid update of disruption mode": { + oldObj: mkValidCompositePodGroup(setResourceVersion("1")), + updateObj: mkValidCompositePodGroup(setResourceVersion("1"), setDisruptionModeAll()), + expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "disruptionMode"), &scheduling.CompositeDisruptionMode{All: &scheduling.AllCompositeDisruptionMode{}}, "field is immutable").WithOrigin("immutable")}, + }, + "valid update with unchanged PreemptionPolicy": { + oldObj: mkValidCompositePodGroup(setResourceVersion("1"), setPreemptionPolicy(scheduling.PreemptLowerPriority)), + updateObj: mkValidCompositePodGroup(setResourceVersion("1"), setPreemptionPolicy(scheduling.PreemptLowerPriority)), + enablePodGroupPreemptionPolicy: true, + }, + "invalid update of PreemptionPolicy": { + oldObj: mkValidCompositePodGroup(setResourceVersion("1"), setPreemptionPolicy(scheduling.PreemptLowerPriority)), + updateObj: mkValidCompositePodGroup(setResourceVersion("1"), setPreemptionPolicy(scheduling.PreemptNever)), + enablePodGroupPreemptionPolicy: true, + expectedErrs: field.ErrorList{ + field.Invalid(field.NewPath("spec", "preemptionPolicy"), nil, "").WithOrigin("immutable"), + }, + }, + "valid update with unchanged PreemptionPolicy when PodGroupPreemptionPolicy is disabled": { + oldObj: mkValidCompositePodGroup(setResourceVersion("1"), setPreemptionPolicy(scheduling.PreemptLowerPriority)), + updateObj: mkValidCompositePodGroup(setResourceVersion("1"), setPreemptionPolicy(scheduling.PreemptLowerPriority)), + enablePodGroupPreemptionPolicy: false, + }, + "invalid update of PreemptionPolicy when PodGroupPreemptionPolicy is disabled": { + oldObj: mkValidCompositePodGroup(setResourceVersion("1"), setPreemptionPolicy(scheduling.PreemptLowerPriority)), + updateObj: mkValidCompositePodGroup(setResourceVersion("1"), setPreemptionPolicy(scheduling.PreemptNever)), + enablePodGroupPreemptionPolicy: false, + expectedErrs: field.ErrorList{ + field.Forbidden(field.NewPath("spec", "preemptionPolicy"), ""), + field.Invalid(field.NewPath("spec", "preemptionPolicy"), nil, "").WithOrigin("immutable"), + }, + }, } for k, tc := range testCases { @@ -264,6 +333,7 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) { features.GenericWorkload: true, features.CompositePodGroup: true, features.TopologyAwareWorkloadScheduling: true, + features.PodGroupPreemptionPolicy: tc.enablePodGroupPreemptionPolicy, }) strategy := registry.NewStrategy() apitesting.VerifyUpdateValidationEquivalence(t, ctx, &tc.updateObj, &tc.oldObj, strategy, tc.expectedErrs) @@ -353,6 +423,9 @@ func mkValidCompositePodGroup(tweaks ...func(cpg *scheduling.CompositePodGroup)) SchedulingPolicy: scheduling.CompositePodGroupSchedulingPolicy{ Basic: &scheduling.CompositeBasicSchedulingPolicy{}, }, + DisruptionMode: &scheduling.CompositeDisruptionMode{ + Single: &scheduling.SingleCompositeDisruptionMode{}, + }, }, } for _, tweak := range tweaks { @@ -373,6 +446,47 @@ func setParentCompositePodGroupName(name string) func(obj *scheduling.CompositeP } } +func setDisruptionModeAll() func(obj *scheduling.CompositePodGroup) { + return func(obj *scheduling.CompositePodGroup) { + obj.Spec.DisruptionMode = &scheduling.CompositeDisruptionMode{ + All: &scheduling.AllCompositeDisruptionMode{}, + } + } +} + +func setDisruptionModeNeither() func(obj *scheduling.CompositePodGroup) { + return func(obj *scheduling.CompositePodGroup) { + obj.Spec.DisruptionMode = &scheduling.CompositeDisruptionMode{} + } +} + +func setDisruptionModeBoth() func(obj *scheduling.CompositePodGroup) { + return func(obj *scheduling.CompositePodGroup) { + obj.Spec.DisruptionMode = &scheduling.CompositeDisruptionMode{ + Single: &scheduling.SingleCompositeDisruptionMode{}, + All: &scheduling.AllCompositeDisruptionMode{}, + } + } +} + +func clearDisruptionMode() func(obj *scheduling.CompositePodGroup) { + return func(obj *scheduling.CompositePodGroup) { + obj.Spec.DisruptionMode = nil + } +} + +func setPreemptionPolicy(policy scheduling.PreemptionPolicy) func(obj *scheduling.CompositePodGroup) { + return func(obj *scheduling.CompositePodGroup) { + obj.Spec.PreemptionPolicy = &policy + } +} + +func clearPreemptionPolicy() func(obj *scheduling.CompositePodGroup) { + return func(obj *scheduling.CompositePodGroup) { + obj.Spec.PreemptionPolicy = nil + } +} + func setPriority(priority int32) func(obj *scheduling.CompositePodGroup) { return func(obj *scheduling.CompositePodGroup) { obj.Spec.Priority = &priority diff --git a/test/declarative_validation/scheduling/compositepodgroup/zz_generated.validations.v1alpha3_test.go b/test/declarative_validation/scheduling/compositepodgroup/zz_generated.validations.v1alpha3_test.go index 5a41e9c6e0e..13ff18f2ded 100644 --- a/test/declarative_validation/scheduling/compositepodgroup/zz_generated.validations.v1alpha3_test.go +++ b/test/declarative_validation/scheduling/compositepodgroup/zz_generated.validations.v1alpha3_test.go @@ -61,10 +61,20 @@ func init() { "metadata.uid": { {ErrorType: "FieldValueInvalid", Origin: "immutable"}, }, + "spec.disruptionMode": { + {ErrorType: "FieldValueInvalid", Origin: "immutable"}, + {ErrorType: "FieldValueInvalid", Origin: "union"}, + {ErrorType: "FieldValueRequired"}, + }, "spec.parentCompositePodGroupName": { {ErrorType: "FieldValueInvalid", Origin: "format=k8s-long-name"}, {ErrorType: "FieldValueInvalid", Origin: "immutable"}, }, + "spec.preemptionPolicy": { + {ErrorType: "FieldValueForbidden"}, + {ErrorType: "FieldValueInvalid", Origin: "immutable"}, + {ErrorType: "FieldValueNotSupported"}, + }, "spec.priority": { {ErrorType: "FieldValueInvalid", Origin: "immutable"}, {ErrorType: "FieldValueInvalid", Origin: "maximum"}, diff --git a/test/declarative_validation/scheduling/workload/declarative_validation_test.go b/test/declarative_validation/scheduling/workload/declarative_validation_test.go index 6d8dd51ef3b..03f55dcb561 100644 --- a/test/declarative_validation/scheduling/workload/declarative_validation_test.go +++ b/test/declarative_validation/scheduling/workload/declarative_validation_test.go @@ -429,6 +429,28 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) { field.Invalid(field.NewPath("spec"), nil, "detected multiple priority configurations").MarkFromImperative(), }, }, + "cpg disruption mode single": { + input: mkValidWorkload(setCPGDisruptionModeSingle(0)), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + }, + "cpg disruption mode all": { + input: mkValidWorkload(setCPGDisruptionModeAll(0)), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + }, + "cpg disruption mode with neither single nor all": { + input: mkValidWorkload(setCPGDisruptionModeNeither(0)), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "compositePodGroupTemplates").Index(0).Child("disruptionMode"), nil, "").WithOrigin("union")}, + }, + "cpg disruption mode with both single and all": { + input: mkValidWorkload(setCPGDisruptionModeBoth(0)), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "compositePodGroupTemplates").Index(0).Child("disruptionMode"), nil, "").WithOrigin("union")}, + }, "cpg policy missing gang": { input: mkValidWorkload(setCPGPolicyEmpty(0)), enableCompositePodGroup: true, @@ -734,6 +756,30 @@ func testDeclarativeValidate(t *testing.T, apiVersion string) { enableCompositePodGroup: true, expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec", "compositePodGroupTemplates").Index(0).Child("schedulingConstraints", "topology").Index(0).Child("key"), nil, "").WithOrigin("format=k8s-label-key")}, }, + "valid cpg PreemptionPolicy": { + input: mkValidWorkload(setCPGPreemptionPolicy(0, scheduling.PreemptLowerPriority)), + enableTopologyAwareScheduling: true, + enableCompositePodGroup: true, + enablePodGroupPreemptionPolicy: true, + }, + "invalid cpg PreemptionPolicy": { + input: mkValidWorkload(setCPGPreemptionPolicy(0, scheduling.PreemptionPolicy("Invalid"))), + enableTopologyAwareScheduling: true, + enableCompositePodGroup: true, + enablePodGroupPreemptionPolicy: true, + expectedErrs: field.ErrorList{ + field.NotSupported(field.NewPath("spec", "compositePodGroupTemplates").Index(0).Child("preemptionPolicy"), scheduling.PreemptionPolicy("Invalid"), []string{"Never", "PreemptLowerPriority"}), + }, + }, + "forbidden cpg PreemptionPolicy when PodGroupPreemptionPolicy is disabled": { + input: mkValidWorkload(setCPGPreemptionPolicy(0, scheduling.PreemptLowerPriority)), + enableTopologyAwareScheduling: true, + enableCompositePodGroup: true, + enablePodGroupPreemptionPolicy: false, + expectedErrs: field.ErrorList{ + field.Forbidden(field.NewPath("spec", "compositePodGroupTemplates").Index(0).Child("preemptionPolicy"), ""), + }, + }, } for k, tc := range testCases { t.Run(k, func(t *testing.T) { @@ -1137,6 +1183,15 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) { field.Forbidden(field.NewPath("spec", "compositePodGroupTemplates").Index(0).Child("podGroupTemplates").Index(1), "").WithOrigin("update"), }, }, + "invalid update immutable cpg disruptionMode": { + oldObj: mkValidWorkload(setResourceVersion("1"), setCPGDisruptionModeSingle(0)), + updateObj: mkValidWorkload(setResourceVersion("1"), setCPGDisruptionModeAll(0)), + enableCompositePodGroup: true, + enableTopologyAwareScheduling: true, + expectedErrs: field.ErrorList{ + field.Invalid(field.NewPath("spec", "compositePodGroupTemplates").Index(0).Child("disruptionMode"), nil, "field is immutable").WithOrigin("immutable"), + }, + }, "invalid update immutable nested pg disruptionMode": { oldObj: mkValidWorkload(setResourceVersion("1"), addCompositePodGroupTemplate(), setNestedPGDisruptionModeSingle(0, 0)), updateObj: mkValidWorkload(setResourceVersion("1"), addCompositePodGroupTemplate(), setNestedPGDisruptionModeAll(0, 0)), @@ -1293,6 +1348,41 @@ func testDeclarativeValidateUpdate(t *testing.T, apiVersion string) { field.Invalid(field.NewPath("spec", "compositePodGroupTemplates").Index(0).Child("schedulingConstraints"), nil, "field is immutable").WithOrigin("immutable"), }, }, + "valid update with unchanged cpg PreemptionPolicy": { + oldObj: mkValidWorkload(setResourceVersion("1"), setCPGPreemptionPolicy(0, scheduling.PreemptLowerPriority)), + updateObj: mkValidWorkload(setResourceVersion("1"), setCPGPreemptionPolicy(0, scheduling.PreemptLowerPriority)), + enableTopologyAwareScheduling: true, + enableCompositePodGroup: true, + enablePodGroupPreemptionPolicy: true, + }, + "invalid update of cpg PreemptionPolicy": { + oldObj: mkValidWorkload(setResourceVersion("1"), setCPGPreemptionPolicy(0, scheduling.PreemptLowerPriority)), + updateObj: mkValidWorkload(setResourceVersion("1"), setCPGPreemptionPolicy(0, scheduling.PreemptNever)), + enableTopologyAwareScheduling: true, + enableCompositePodGroup: true, + enablePodGroupPreemptionPolicy: true, + expectedErrs: field.ErrorList{ + field.Invalid(field.NewPath("spec", "compositePodGroupTemplates").Index(0).Child("preemptionPolicy"), nil, "").WithOrigin("immutable"), + }, + }, + "valid update with unchanged cpg PreemptionPolicy when PodGroupPreemptionPolicy is disabled": { + oldObj: mkValidWorkload(setResourceVersion("1"), setCPGPreemptionPolicy(0, scheduling.PreemptLowerPriority)), + updateObj: mkValidWorkload(setResourceVersion("1"), setCPGPreemptionPolicy(0, scheduling.PreemptLowerPriority)), + enableTopologyAwareScheduling: true, + enableCompositePodGroup: true, + enablePodGroupPreemptionPolicy: false, + }, + "invalid update of cpg PreemptionPolicy when PodGroupPreemptionPolicy is disabled": { + oldObj: mkValidWorkload(setResourceVersion("1"), setCPGPreemptionPolicy(0, scheduling.PreemptLowerPriority)), + updateObj: mkValidWorkload(setResourceVersion("1"), setCPGPreemptionPolicy(0, scheduling.PreemptNever)), + enableTopologyAwareScheduling: true, + enableCompositePodGroup: true, + enablePodGroupPreemptionPolicy: false, + expectedErrs: field.ErrorList{ + field.Forbidden(field.NewPath("spec", "compositePodGroupTemplates").Index(0).Child("preemptionPolicy"), ""), + field.Invalid(field.NewPath("spec", "compositePodGroupTemplates").Index(0).Child("preemptionPolicy"), nil, "").WithOrigin("immutable"), + }, + }, } ctx := genericapirequest.WithRequestInfo(genericapirequest.NewDefaultContext(), &genericapirequest.RequestInfo{ APIPrefix: "apis", @@ -1629,6 +1719,41 @@ func addNestedCompositePodGroupTemplate(idx int, names ...string) func(obj *sche } } +func setCPGDisruptionModeSingle(idx int) func(obj *scheduling.Workload) { + return func(obj *scheduling.Workload) { + addCompositePodGroupTemplate()(obj) + obj.Spec.CompositePodGroupTemplates[idx].DisruptionMode = &scheduling.CompositeDisruptionMode{ + Single: &scheduling.SingleCompositeDisruptionMode{}, + } + } +} + +func setCPGDisruptionModeAll(idx int) func(obj *scheduling.Workload) { + return func(obj *scheduling.Workload) { + addCompositePodGroupTemplate()(obj) + obj.Spec.CompositePodGroupTemplates[idx].DisruptionMode = &scheduling.CompositeDisruptionMode{ + All: &scheduling.AllCompositeDisruptionMode{}, + } + } +} + +func setCPGDisruptionModeNeither(idx int) func(obj *scheduling.Workload) { + return func(obj *scheduling.Workload) { + addCompositePodGroupTemplate()(obj) + obj.Spec.CompositePodGroupTemplates[idx].DisruptionMode = &scheduling.CompositeDisruptionMode{} + } +} + +func setCPGDisruptionModeBoth(idx int) func(obj *scheduling.Workload) { + return func(obj *scheduling.Workload) { + addCompositePodGroupTemplate()(obj) + obj.Spec.CompositePodGroupTemplates[idx].DisruptionMode = &scheduling.CompositeDisruptionMode{ + Single: &scheduling.SingleCompositeDisruptionMode{}, + All: &scheduling.AllCompositeDisruptionMode{}, + } + } +} + func setCPGPriorityClassName(idx int, priorityClassName string) func(obj *scheduling.Workload) { return func(obj *scheduling.Workload) { addCompositePodGroupTemplate()(obj) @@ -1966,3 +2091,10 @@ func addCPGTopologyConstraint(cpgIdx int, topologyKey string) func(obj *scheduli scheduling.TopologyConstraint{Key: topologyKey}) } } + +func setCPGPreemptionPolicy(cidx int, policy scheduling.PreemptionPolicy) func(obj *scheduling.Workload) { + return func(obj *scheduling.Workload) { + addCompositePodGroupTemplate()(obj) + obj.Spec.CompositePodGroupTemplates[cidx].PreemptionPolicy = &policy + } +} diff --git a/test/declarative_validation/scheduling/workload/zz_generated.validations.v1alpha3_test.go b/test/declarative_validation/scheduling/workload/zz_generated.validations.v1alpha3_test.go index 9e859bfd4ca..19e343aba26 100644 --- a/test/declarative_validation/scheduling/workload/zz_generated.validations.v1alpha3_test.go +++ b/test/declarative_validation/scheduling/workload/zz_generated.validations.v1alpha3_test.go @@ -81,6 +81,10 @@ func init() { {ErrorType: "FieldValueDuplicate"}, {ErrorType: "FieldValueForbidden", Origin: "update"}, }, + "spec.compositePodGroupTemplates[*].disruptionMode": { + {ErrorType: "FieldValueInvalid", Origin: "immutable"}, + {ErrorType: "FieldValueInvalid", Origin: "union"}, + }, "spec.compositePodGroupTemplates[*].name": { {ErrorType: "FieldValueInvalid", Origin: "format=k8s-short-name"}, {ErrorType: "FieldValueRequired"}, @@ -156,6 +160,11 @@ func init() { {ErrorType: "FieldValueInvalid", Origin: "minimum"}, {ErrorType: "FieldValueRequired"}, }, + "spec.compositePodGroupTemplates[*].preemptionPolicy": { + {ErrorType: "FieldValueForbidden"}, + {ErrorType: "FieldValueInvalid", Origin: "immutable"}, + {ErrorType: "FieldValueNotSupported"}, + }, "spec.compositePodGroupTemplates[*].priority": { {ErrorType: "FieldValueInvalid", Origin: "immutable"}, {ErrorType: "FieldValueInvalid", Origin: "maximum"}, diff --git a/test/declarative_validation/scheduling/workload/zz_generated.validations.v1beta1_test.go b/test/declarative_validation/scheduling/workload/zz_generated.validations.v1beta1_test.go index ce8be6b7df5..ba3e024782a 100644 --- a/test/declarative_validation/scheduling/workload/zz_generated.validations.v1beta1_test.go +++ b/test/declarative_validation/scheduling/workload/zz_generated.validations.v1beta1_test.go @@ -81,6 +81,10 @@ func init() { {ErrorType: "FieldValueDuplicate"}, {ErrorType: "FieldValueForbidden", Origin: "update"}, }, + "spec.compositePodGroupTemplates[*].disruptionMode": { + {ErrorType: "FieldValueInvalid", Origin: "immutable"}, + {ErrorType: "FieldValueInvalid", Origin: "union"}, + }, "spec.compositePodGroupTemplates[*].name": { {ErrorType: "FieldValueInvalid", Origin: "format=k8s-short-name"}, {ErrorType: "FieldValueRequired"}, @@ -156,6 +160,11 @@ func init() { {ErrorType: "FieldValueInvalid", Origin: "minimum"}, {ErrorType: "FieldValueRequired"}, }, + "spec.compositePodGroupTemplates[*].preemptionPolicy": { + {ErrorType: "FieldValueForbidden"}, + {ErrorType: "FieldValueInvalid", Origin: "immutable"}, + {ErrorType: "FieldValueNotSupported"}, + }, "spec.compositePodGroupTemplates[*].priority": { {ErrorType: "FieldValueInvalid", Origin: "immutable"}, {ErrorType: "FieldValueInvalid", Origin: "maximum"},