From 2743acf78fe1b88688b842debc860e91cfa93a20 Mon Sep 17 00:00:00 2001 From: ravisantoshgudimetla Date: Mon, 9 Aug 2021 15:47:15 -0400 Subject: [PATCH 1/5] [cc] [staging]:Introduce scheduler v1beta3 api Staging changes for scheduler v1beta3 api. xref: https://github.com/kubernetes/enhancements/pull/2850 --- .../kube-scheduler/config/v1beta3/doc.go | 21 + .../kube-scheduler/config/v1beta3/register.go | 50 ++ .../kube-scheduler/config/v1beta3/types.go | 305 ++++++++++ .../config/v1beta3/types_pluginargs.go | 226 +++++++ .../config/v1beta3/zz_generated.deepcopy.go | 556 ++++++++++++++++++ 5 files changed, 1158 insertions(+) create mode 100644 staging/src/k8s.io/kube-scheduler/config/v1beta3/doc.go create mode 100644 staging/src/k8s.io/kube-scheduler/config/v1beta3/register.go create mode 100644 staging/src/k8s.io/kube-scheduler/config/v1beta3/types.go create mode 100644 staging/src/k8s.io/kube-scheduler/config/v1beta3/types_pluginargs.go create mode 100644 staging/src/k8s.io/kube-scheduler/config/v1beta3/zz_generated.deepcopy.go diff --git a/staging/src/k8s.io/kube-scheduler/config/v1beta3/doc.go b/staging/src/k8s.io/kube-scheduler/config/v1beta3/doc.go new file mode 100644 index 0000000000000..c791874d61158 --- /dev/null +++ b/staging/src/k8s.io/kube-scheduler/config/v1beta3/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2021 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. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:openapi-gen=true +// +groupName=kubescheduler.config.k8s.io + +package v1beta3 // import "k8s.io/kube-scheduler/config/v1beta3" diff --git a/staging/src/k8s.io/kube-scheduler/config/v1beta3/register.go b/staging/src/k8s.io/kube-scheduler/config/v1beta3/register.go new file mode 100644 index 0000000000000..768f107b4e816 --- /dev/null +++ b/staging/src/k8s.io/kube-scheduler/config/v1beta3/register.go @@ -0,0 +1,50 @@ +/* +Copyright 2021 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. +*/ + +package v1beta3 + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name used in this package +const GroupName = "kubescheduler.config.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta3"} + +var ( + // SchemeBuilder is the scheme builder with scheme init functions to run for this API package + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme is a global function that registers this API group & version to a scheme + AddToScheme = SchemeBuilder.AddToScheme +) + +// addKnownTypes registers known types to the given scheme +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &KubeSchedulerConfiguration{}, + &DefaultPreemptionArgs{}, + &InterPodAffinityArgs{}, + &NodeResourcesBalancedAllocationArgs{}, + &NodeResourcesFitArgs{}, + &PodTopologySpreadArgs{}, + &VolumeBindingArgs{}, + &NodeAffinityArgs{}, + ) + return nil +} diff --git a/staging/src/k8s.io/kube-scheduler/config/v1beta3/types.go b/staging/src/k8s.io/kube-scheduler/config/v1beta3/types.go new file mode 100644 index 0000000000000..64038aa993765 --- /dev/null +++ b/staging/src/k8s.io/kube-scheduler/config/v1beta3/types.go @@ -0,0 +1,305 @@ +/* +Copyright 2021 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. +*/ + +package v1beta3 + +import ( + "bytes" + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1" + v1 "k8s.io/kube-scheduler/config/v1" + "sigs.k8s.io/yaml" +) + +const ( + // SchedulerDefaultLockObjectNamespace defines default scheduler lock object namespace ("kube-system") + SchedulerDefaultLockObjectNamespace string = metav1.NamespaceSystem + + // SchedulerDefaultLockObjectName defines default scheduler lock object name ("kube-scheduler") + SchedulerDefaultLockObjectName = "kube-scheduler" + + // SchedulerDefaultProviderName defines the default provider names + SchedulerDefaultProviderName = "DefaultProvider" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KubeSchedulerConfiguration configures a scheduler +type KubeSchedulerConfiguration struct { + metav1.TypeMeta `json:",inline"` + + // Parallelism defines the amount of parallelism in algorithms for scheduling a Pods. Must be greater than 0. Defaults to 16 + Parallelism *int32 `json:"parallelism,omitempty"` + + // LeaderElection defines the configuration of leader election client. + LeaderElection componentbaseconfigv1alpha1.LeaderElectionConfiguration `json:"leaderElection"` + + // ClientConnection specifies the kubeconfig file and client connection + // settings for the proxy server to use when communicating with the apiserver. + ClientConnection componentbaseconfigv1alpha1.ClientConnectionConfiguration `json:"clientConnection"` + + // DebuggingConfiguration holds configuration for Debugging related features + // TODO: We might wanna make this a substruct like Debugging componentbaseconfigv1alpha1.DebuggingConfiguration + componentbaseconfigv1alpha1.DebuggingConfiguration `json:",inline"` + + // PercentageOfNodesToScore is the percentage of all nodes that once found feasible + // for running a pod, the scheduler stops its search for more feasible nodes in + // the cluster. This helps improve scheduler's performance. Scheduler always tries to find + // at least "minFeasibleNodesToFind" feasible nodes no matter what the value of this flag is. + // Example: if the cluster size is 500 nodes and the value of this flag is 30, + // then scheduler stops finding further feasible nodes once it finds 150 feasible ones. + // When the value is 0, default percentage (5%--50% based on the size of the cluster) of the + // nodes will be scored. + PercentageOfNodesToScore *int32 `json:"percentageOfNodesToScore,omitempty"` + + // PodInitialBackoffSeconds is the initial backoff for unschedulable pods. + // If specified, it must be greater than 0. If this value is null, the default value (1s) + // will be used. + PodInitialBackoffSeconds *int64 `json:"podInitialBackoffSeconds,omitempty"` + + // PodMaxBackoffSeconds is the max backoff for unschedulable pods. + // If specified, it must be greater than podInitialBackoffSeconds. If this value is null, + // the default value (10s) will be used. + PodMaxBackoffSeconds *int64 `json:"podMaxBackoffSeconds,omitempty"` + + // Profiles are scheduling profiles that kube-scheduler supports. Pods can + // choose to be scheduled under a particular profile by setting its associated + // scheduler name. Pods that don't specify any scheduler name are scheduled + // with the "default-scheduler" profile, if present here. + // +listType=map + // +listMapKey=schedulerName + Profiles []KubeSchedulerProfile `json:"profiles,omitempty"` + + // Extenders are the list of scheduler extenders, each holding the values of how to communicate + // with the extender. These extenders are shared by all scheduler profiles. + // +listType=set + Extenders []Extender `json:"extenders,omitempty"` +} + +// DecodeNestedObjects decodes plugin args for known types. +func (c *KubeSchedulerConfiguration) DecodeNestedObjects(d runtime.Decoder) error { + for i := range c.Profiles { + prof := &c.Profiles[i] + for j := range prof.PluginConfig { + err := prof.PluginConfig[j].decodeNestedObjects(d) + if err != nil { + return fmt.Errorf("decoding .profiles[%d].pluginConfig[%d]: %w", i, j, err) + } + } + } + return nil +} + +// EncodeNestedObjects encodes plugin args. +func (c *KubeSchedulerConfiguration) EncodeNestedObjects(e runtime.Encoder) error { + for i := range c.Profiles { + prof := &c.Profiles[i] + for j := range prof.PluginConfig { + err := prof.PluginConfig[j].encodeNestedObjects(e) + if err != nil { + return fmt.Errorf("encoding .profiles[%d].pluginConfig[%d]: %w", i, j, err) + } + } + } + return nil +} + +// KubeSchedulerProfile is a scheduling profile. +type KubeSchedulerProfile struct { + // SchedulerName is the name of the scheduler associated to this profile. + // If SchedulerName matches with the pod's "spec.schedulerName", then the pod + // is scheduled with this profile. + SchedulerName *string `json:"schedulerName,omitempty"` + + // Plugins specify the set of plugins that should be enabled or disabled. + // Enabled plugins are the ones that should be enabled in addition to the + // default plugins. Disabled plugins are any of the default plugins that + // should be disabled. + // When no enabled or disabled plugin is specified for an extension point, + // default plugins for that extension point will be used if there is any. + // If a QueueSort plugin is specified, the same QueueSort Plugin and + // PluginConfig must be specified for all profiles. + Plugins *Plugins `json:"plugins,omitempty"` + + // PluginConfig is an optional set of custom plugin arguments for each plugin. + // Omitting config args for a plugin is equivalent to using the default config + // for that plugin. + // +listType=map + // +listMapKey=name + PluginConfig []PluginConfig `json:"pluginConfig,omitempty"` +} + +// Plugins include multiple extension points. When specified, the list of plugins for +// a particular extension point are the only ones enabled. If an extension point is +// omitted from the config, then the default set of plugins is used for that extension point. +// Enabled plugins are called in the order specified here, after default plugins. If they need to +// be invoked before default plugins, default plugins must be disabled and re-enabled here in desired order. +type Plugins struct { + // QueueSort is a list of plugins that should be invoked when sorting pods in the scheduling queue. + QueueSort PluginSet `json:"queueSort,omitempty"` + + // PreFilter is a list of plugins that should be invoked at "PreFilter" extension point of the scheduling framework. + PreFilter PluginSet `json:"preFilter,omitempty"` + + // Filter is a list of plugins that should be invoked when filtering out nodes that cannot run the Pod. + Filter PluginSet `json:"filter,omitempty"` + + // PostFilter is a list of plugins that are invoked after filtering phase, no matter whether filtering succeeds or not. + PostFilter PluginSet `json:"postFilter,omitempty"` + + // PreScore is a list of plugins that are invoked before scoring. + PreScore PluginSet `json:"preScore,omitempty"` + + // Score is a list of plugins that should be invoked when ranking nodes that have passed the filtering phase. + Score PluginSet `json:"score,omitempty"` + + // Reserve is a list of plugins invoked when reserving/unreserving resources + // after a node is assigned to run the pod. + Reserve PluginSet `json:"reserve,omitempty"` + + // Permit is a list of plugins that control binding of a Pod. These plugins can prevent or delay binding of a Pod. + Permit PluginSet `json:"permit,omitempty"` + + // PreBind is a list of plugins that should be invoked before a pod is bound. + PreBind PluginSet `json:"preBind,omitempty"` + + // Bind is a list of plugins that should be invoked at "Bind" extension point of the scheduling framework. + // The scheduler call these plugins in order. Scheduler skips the rest of these plugins as soon as one returns success. + Bind PluginSet `json:"bind,omitempty"` + + // PostBind is a list of plugins that should be invoked after a pod is successfully bound. + PostBind PluginSet `json:"postBind,omitempty"` +} + +// PluginSet specifies enabled and disabled plugins for an extension point. +// If an array is empty, missing, or nil, default plugins at that extension point will be used. +type PluginSet struct { + // Enabled specifies plugins that should be enabled in addition to default plugins. + // If the default plugin is also configured in the scheduler config file, the weight of plugin will + // be overridden accordingly. + // These are called after default plugins and in the same order specified here. + // +listType=atomic + Enabled []Plugin `json:"enabled,omitempty"` + // Disabled specifies default plugins that should be disabled. + // When all default plugins need to be disabled, an array containing only one "*" should be provided. + // +listType=map + // +listMapKey=name + Disabled []Plugin `json:"disabled,omitempty"` +} + +// Plugin specifies a plugin name and its weight when applicable. Weight is used only for Score plugins. +type Plugin struct { + // Name defines the name of plugin + Name string `json:"name"` + // Weight defines the weight of plugin, only used for Score plugins. + Weight *int32 `json:"weight,omitempty"` +} + +// PluginConfig specifies arguments that should be passed to a plugin at the time of initialization. +// A plugin that is invoked at multiple extension points is initialized once. Args can have arbitrary structure. +// It is up to the plugin to process these Args. +type PluginConfig struct { + // Name defines the name of plugin being configured + Name string `json:"name"` + // Args defines the arguments passed to the plugins at the time of initialization. Args can have arbitrary structure. + Args runtime.RawExtension `json:"args,omitempty"` +} + +func (c *PluginConfig) decodeNestedObjects(d runtime.Decoder) error { + gvk := SchemeGroupVersion.WithKind(c.Name + "Args") + // dry-run to detect and skip out-of-tree plugin args. + if _, _, err := d.Decode(nil, &gvk, nil); runtime.IsNotRegisteredError(err) { + return nil + } + + obj, parsedGvk, err := d.Decode(c.Args.Raw, &gvk, nil) + if err != nil { + return fmt.Errorf("decoding args for plugin %s: %w", c.Name, err) + } + if parsedGvk.GroupKind() != gvk.GroupKind() { + return fmt.Errorf("args for plugin %s were not of type %s, got %s", c.Name, gvk.GroupKind(), parsedGvk.GroupKind()) + } + c.Args.Object = obj + return nil +} + +func (c *PluginConfig) encodeNestedObjects(e runtime.Encoder) error { + if c.Args.Object == nil { + return nil + } + var buf bytes.Buffer + err := e.Encode(c.Args.Object, &buf) + if err != nil { + return err + } + // The encoder might be a YAML encoder, but the parent encoder expects + // JSON output, so we convert YAML back to JSON. + // This is a no-op if produces JSON. + json, err := yaml.YAMLToJSON(buf.Bytes()) + if err != nil { + return err + } + c.Args.Raw = json + return nil +} + +// Extender holds the parameters used to communicate with the extender. If a verb is unspecified/empty, +// it is assumed that the extender chose not to provide that extension. +type Extender struct { + // URLPrefix at which the extender is available + URLPrefix string `json:"urlPrefix"` + // Verb for the filter call, empty if not supported. This verb is appended to the URLPrefix when issuing the filter call to extender. + FilterVerb string `json:"filterVerb,omitempty"` + // Verb for the preempt call, empty if not supported. This verb is appended to the URLPrefix when issuing the preempt call to extender. + PreemptVerb string `json:"preemptVerb,omitempty"` + // Verb for the prioritize call, empty if not supported. This verb is appended to the URLPrefix when issuing the prioritize call to extender. + PrioritizeVerb string `json:"prioritizeVerb,omitempty"` + // The numeric multiplier for the node scores that the prioritize call generates. + // The weight should be a positive integer + Weight int64 `json:"weight,omitempty"` + // Verb for the bind call, empty if not supported. This verb is appended to the URLPrefix when issuing the bind call to extender. + // If this method is implemented by the extender, it is the extender's responsibility to bind the pod to apiserver. Only one extender + // can implement this function. + BindVerb string `json:"bindVerb,omitempty"` + // EnableHTTPS specifies whether https should be used to communicate with the extender + EnableHTTPS bool `json:"enableHTTPS,omitempty"` + // TLSConfig specifies the transport layer security config + TLSConfig *v1.ExtenderTLSConfig `json:"tlsConfig,omitempty"` + // HTTPTimeout specifies the timeout duration for a call to the extender. Filter timeout fails the scheduling of the pod. Prioritize + // timeout is ignored, k8s/other extenders priorities are used to select the node. + HTTPTimeout metav1.Duration `json:"httpTimeout,omitempty"` + // NodeCacheCapable specifies that the extender is capable of caching node information, + // so the scheduler should only send minimal information about the eligible nodes + // assuming that the extender already cached full details of all nodes in the cluster + NodeCacheCapable bool `json:"nodeCacheCapable,omitempty"` + // ManagedResources is a list of extended resources that are managed by + // this extender. + // - A pod will be sent to the extender on the Filter, Prioritize and Bind + // (if the extender is the binder) phases iff the pod requests at least + // one of the extended resources in this list. If empty or unspecified, + // all pods will be sent to this extender. + // - If IgnoredByScheduler is set to true for a resource, kube-scheduler + // will skip checking the resource in predicates. + // +optional + // +listType=atomic + ManagedResources []v1.ExtenderManagedResource `json:"managedResources,omitempty"` + // Ignorable specifies if the extender is ignorable, i.e. scheduling should not + // fail when the extender returns an error or is not reachable. + Ignorable bool `json:"ignorable,omitempty"` +} diff --git a/staging/src/k8s.io/kube-scheduler/config/v1beta3/types_pluginargs.go b/staging/src/k8s.io/kube-scheduler/config/v1beta3/types_pluginargs.go new file mode 100644 index 0000000000000..2c3fa4cbbe0cb --- /dev/null +++ b/staging/src/k8s.io/kube-scheduler/config/v1beta3/types_pluginargs.go @@ -0,0 +1,226 @@ +/* +Copyright 2021 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. +*/ + +package v1beta3 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// DefaultPreemptionArgs holds arguments used to configure the +// DefaultPreemption plugin. +type DefaultPreemptionArgs struct { + metav1.TypeMeta `json:",inline"` + + // MinCandidateNodesPercentage is the minimum number of candidates to + // shortlist when dry running preemption as a percentage of number of nodes. + // Must be in the range [0, 100]. Defaults to 10% of the cluster size if + // unspecified. + MinCandidateNodesPercentage *int32 `json:"minCandidateNodesPercentage,omitempty"` + // MinCandidateNodesAbsolute is the absolute minimum number of candidates to + // shortlist. The likely number of candidates enumerated for dry running + // preemption is given by the formula: + // numCandidates = max(numNodes * minCandidateNodesPercentage, minCandidateNodesAbsolute) + // We say "likely" because there are other factors such as PDB violations + // that play a role in the number of candidates shortlisted. Must be at least + // 0 nodes. Defaults to 100 nodes if unspecified. + MinCandidateNodesAbsolute *int32 `json:"minCandidateNodesAbsolute,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// InterPodAffinityArgs holds arguments used to configure the InterPodAffinity plugin. +type InterPodAffinityArgs struct { + metav1.TypeMeta `json:",inline"` + + // HardPodAffinityWeight is the scoring weight for existing pods with a + // matching hard affinity to the incoming pod. + HardPodAffinityWeight *int32 `json:"hardPodAffinityWeight,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// NodeResourcesFitArgs holds arguments used to configure the NodeResourcesFit plugin. +type NodeResourcesFitArgs struct { + metav1.TypeMeta `json:",inline"` + + // IgnoredResources is the list of resources that NodeResources fit filter + // should ignore. This doesn't apply to scoring. + // +listType=atomic + IgnoredResources []string `json:"ignoredResources,omitempty"` + // IgnoredResourceGroups defines the list of resource groups that NodeResources fit filter should ignore. + // e.g. if group is ["example.com"], it will ignore all resource names that begin + // with "example.com", such as "example.com/aaa" and "example.com/bbb". + // A resource group name can't contain '/'. This doesn't apply to scoring. + // +listType=atomic + IgnoredResourceGroups []string `json:"ignoredResourceGroups,omitempty"` + + // ScoringStrategy selects the node resource scoring strategy. + // The default strategy is LeastAllocated with an equal "cpu" and "memory" weight. + ScoringStrategy *ScoringStrategy `json:"scoringStrategy,omitempty"` +} + +// PodTopologySpreadConstraintsDefaulting defines how to set default constraints +// for the PodTopologySpread plugin. +type PodTopologySpreadConstraintsDefaulting string + +const ( + // SystemDefaulting instructs to use the kubernetes defined default. + SystemDefaulting PodTopologySpreadConstraintsDefaulting = "System" + // ListDefaulting instructs to use the config provided default. + ListDefaulting PodTopologySpreadConstraintsDefaulting = "List" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PodTopologySpreadArgs holds arguments used to configure the PodTopologySpread plugin. +type PodTopologySpreadArgs struct { + metav1.TypeMeta `json:",inline"` + + // DefaultConstraints defines topology spread constraints to be applied to + // Pods that don't define any in `pod.spec.topologySpreadConstraints`. + // `.defaultConstraints[*].labelSelectors` must be empty, as they are + // deduced from the Pod's membership to Services, ReplicationControllers, + // ReplicaSets or StatefulSets. + // When not empty, .defaultingType must be "List". + // +optional + // +listType=atomic + DefaultConstraints []corev1.TopologySpreadConstraint `json:"defaultConstraints,omitempty"` + + // DefaultingType determines how .defaultConstraints are deduced. Can be one + // of "System" or "List". + // + // - "System": Use kubernetes defined constraints that spread Pods among + // Nodes and Zones. + // - "List": Use constraints defined in .defaultConstraints. + // + // Defaults to "List" if feature gate DefaultPodTopologySpread is disabled + // and to "System" if enabled. + // +optional + DefaultingType PodTopologySpreadConstraintsDefaulting `json:"defaultingType,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// NodeResourcesBalancedAllocationArgs holds arguments used to configure NodeResourcesBalancedAllocation plugin. +type NodeResourcesBalancedAllocationArgs struct { + metav1.TypeMeta `json:",inline"` + + // Resources to be managed, the default is "cpu" and "memory" if not specified. + // +listType=map + // +listMapKey=name + Resources []ResourceSpec `json:"resources,omitempty"` +} + +// UtilizationShapePoint represents single point of priority function shape. +type UtilizationShapePoint struct { + // Utilization (x axis). Valid values are 0 to 100. Fully utilized node maps to 100. + Utilization int32 `json:"utilization"` + // Score assigned to given utilization (y axis). Valid values are 0 to 10. + Score int32 `json:"score"` +} + +// ResourceSpec represents a single resource. +type ResourceSpec struct { + // Name of the resource. + Name string `json:"name"` + // Weight of the resource. + Weight int64 `json:"weight,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeBindingArgs holds arguments used to configure the VolumeBinding plugin. +type VolumeBindingArgs struct { + metav1.TypeMeta `json:",inline"` + + // BindTimeoutSeconds is the timeout in seconds in volume binding operation. + // Value must be non-negative integer. The value zero indicates no waiting. + // If this value is nil, the default value (600) will be used. + BindTimeoutSeconds *int64 `json:"bindTimeoutSeconds,omitempty"` + + // Shape specifies the points defining the score function shape, which is + // used to score nodes based on the utilization of statically provisioned + // PVs. The utilization is calculated by dividing the total requested + // storage of the pod by the total capacity of feasible PVs on each node. + // Each point contains utilization (ranges from 0 to 100) and its + // associated score (ranges from 0 to 10). You can turn the priority by + // specifying different scores for different utilization numbers. + // The default shape points are: + // 1) 0 for 0 utilization + // 2) 10 for 100 utilization + // All points must be sorted in increasing order by utilization. + // +featureGate=VolumeCapacityPriority + // +optional + // +listType=atomic + Shape []UtilizationShapePoint `json:"shape,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// NodeAffinityArgs holds arguments to configure the NodeAffinity plugin. +type NodeAffinityArgs struct { + metav1.TypeMeta `json:",inline"` + + // AddedAffinity is applied to all Pods additionally to the NodeAffinity + // specified in the PodSpec. That is, Nodes need to satisfy AddedAffinity + // AND .spec.NodeAffinity. AddedAffinity is empty by default (all Nodes + // match). + // When AddedAffinity is used, some Pods with affinity requirements that match + // a specific Node (such as Daemonset Pods) might remain unschedulable. + // +optional + AddedAffinity *corev1.NodeAffinity `json:"addedAffinity,omitempty"` +} + +// ScoringStrategyType the type of scoring strategy used in NodeResourcesFit plugin. +type ScoringStrategyType string + +const ( + // LeastAllocated strategy prioritizes nodes with least allcoated resources. + LeastAllocated ScoringStrategyType = "LeastAllocated" + // MostAllocated strategy prioritizes nodes with most allcoated resources. + MostAllocated ScoringStrategyType = "MostAllocated" + // RequestedToCapacityRatio strategy allows specifying a custom shape function + // to score nodes based on the request to capacity ratio. + RequestedToCapacityRatio ScoringStrategyType = "RequestedToCapacityRatio" +) + +// ScoringStrategy define ScoringStrategyType for node resource plugin +type ScoringStrategy struct { + // Type selects which strategy to run. + Type ScoringStrategyType `json:"type,omitempty"` + + // Resources to consider when scoring. + // The default resource set includes "cpu" and "memory" with an equal weight. + // Allowed weights go from 1 to 100. + // Weight defaults to 1 if not specified or explicitly set to 0. + // +listType=map + // +listMapKey=topologyKey + Resources []ResourceSpec `json:"resources,omitempty"` + + // Arguments specific to RequestedToCapacityRatio strategy. + RequestedToCapacityRatio *RequestedToCapacityRatioParam `json:"requestedToCapacityRatio,omitempty"` +} + +// RequestedToCapacityRatioParam define RequestedToCapacityRatio parameters +type RequestedToCapacityRatioParam struct { + // Shape is a list of points defining the scoring function shape. + // +listType=atomic + Shape []UtilizationShapePoint `json:"shape,omitempty"` +} diff --git a/staging/src/k8s.io/kube-scheduler/config/v1beta3/zz_generated.deepcopy.go b/staging/src/k8s.io/kube-scheduler/config/v1beta3/zz_generated.deepcopy.go new file mode 100644 index 0000000000000..8d827f0c4e11c --- /dev/null +++ b/staging/src/k8s.io/kube-scheduler/config/v1beta3/zz_generated.deepcopy.go @@ -0,0 +1,556 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +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 deepcopy-gen. DO NOT EDIT. + +package v1beta3 + +import ( + corev1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + v1 "k8s.io/kube-scheduler/config/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DefaultPreemptionArgs) DeepCopyInto(out *DefaultPreemptionArgs) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.MinCandidateNodesPercentage != nil { + in, out := &in.MinCandidateNodesPercentage, &out.MinCandidateNodesPercentage + *out = new(int32) + **out = **in + } + if in.MinCandidateNodesAbsolute != nil { + in, out := &in.MinCandidateNodesAbsolute, &out.MinCandidateNodesAbsolute + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DefaultPreemptionArgs. +func (in *DefaultPreemptionArgs) DeepCopy() *DefaultPreemptionArgs { + if in == nil { + return nil + } + out := new(DefaultPreemptionArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DefaultPreemptionArgs) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Extender) DeepCopyInto(out *Extender) { + *out = *in + if in.TLSConfig != nil { + in, out := &in.TLSConfig, &out.TLSConfig + *out = new(v1.ExtenderTLSConfig) + (*in).DeepCopyInto(*out) + } + out.HTTPTimeout = in.HTTPTimeout + if in.ManagedResources != nil { + in, out := &in.ManagedResources, &out.ManagedResources + *out = make([]v1.ExtenderManagedResource, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Extender. +func (in *Extender) DeepCopy() *Extender { + if in == nil { + return nil + } + out := new(Extender) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InterPodAffinityArgs) DeepCopyInto(out *InterPodAffinityArgs) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.HardPodAffinityWeight != nil { + in, out := &in.HardPodAffinityWeight, &out.HardPodAffinityWeight + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterPodAffinityArgs. +func (in *InterPodAffinityArgs) DeepCopy() *InterPodAffinityArgs { + if in == nil { + return nil + } + out := new(InterPodAffinityArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *InterPodAffinityArgs) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeSchedulerConfiguration) DeepCopyInto(out *KubeSchedulerConfiguration) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.Parallelism != nil { + in, out := &in.Parallelism, &out.Parallelism + *out = new(int32) + **out = **in + } + in.LeaderElection.DeepCopyInto(&out.LeaderElection) + out.ClientConnection = in.ClientConnection + in.DebuggingConfiguration.DeepCopyInto(&out.DebuggingConfiguration) + if in.PercentageOfNodesToScore != nil { + in, out := &in.PercentageOfNodesToScore, &out.PercentageOfNodesToScore + *out = new(int32) + **out = **in + } + if in.PodInitialBackoffSeconds != nil { + in, out := &in.PodInitialBackoffSeconds, &out.PodInitialBackoffSeconds + *out = new(int64) + **out = **in + } + if in.PodMaxBackoffSeconds != nil { + in, out := &in.PodMaxBackoffSeconds, &out.PodMaxBackoffSeconds + *out = new(int64) + **out = **in + } + if in.Profiles != nil { + in, out := &in.Profiles, &out.Profiles + *out = make([]KubeSchedulerProfile, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Extenders != nil { + in, out := &in.Extenders, &out.Extenders + *out = make([]Extender, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeSchedulerConfiguration. +func (in *KubeSchedulerConfiguration) DeepCopy() *KubeSchedulerConfiguration { + if in == nil { + return nil + } + out := new(KubeSchedulerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KubeSchedulerConfiguration) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeSchedulerProfile) DeepCopyInto(out *KubeSchedulerProfile) { + *out = *in + if in.SchedulerName != nil { + in, out := &in.SchedulerName, &out.SchedulerName + *out = new(string) + **out = **in + } + if in.Plugins != nil { + in, out := &in.Plugins, &out.Plugins + *out = new(Plugins) + (*in).DeepCopyInto(*out) + } + if in.PluginConfig != nil { + in, out := &in.PluginConfig, &out.PluginConfig + *out = make([]PluginConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeSchedulerProfile. +func (in *KubeSchedulerProfile) DeepCopy() *KubeSchedulerProfile { + if in == nil { + return nil + } + out := new(KubeSchedulerProfile) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeAffinityArgs) DeepCopyInto(out *NodeAffinityArgs) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.AddedAffinity != nil { + in, out := &in.AddedAffinity, &out.AddedAffinity + *out = new(corev1.NodeAffinity) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeAffinityArgs. +func (in *NodeAffinityArgs) DeepCopy() *NodeAffinityArgs { + if in == nil { + return nil + } + out := new(NodeAffinityArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeAffinityArgs) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeResourcesBalancedAllocationArgs) DeepCopyInto(out *NodeResourcesBalancedAllocationArgs) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]ResourceSpec, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeResourcesBalancedAllocationArgs. +func (in *NodeResourcesBalancedAllocationArgs) DeepCopy() *NodeResourcesBalancedAllocationArgs { + if in == nil { + return nil + } + out := new(NodeResourcesBalancedAllocationArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeResourcesBalancedAllocationArgs) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeResourcesFitArgs) DeepCopyInto(out *NodeResourcesFitArgs) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.IgnoredResources != nil { + in, out := &in.IgnoredResources, &out.IgnoredResources + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.IgnoredResourceGroups != nil { + in, out := &in.IgnoredResourceGroups, &out.IgnoredResourceGroups + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ScoringStrategy != nil { + in, out := &in.ScoringStrategy, &out.ScoringStrategy + *out = new(ScoringStrategy) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeResourcesFitArgs. +func (in *NodeResourcesFitArgs) DeepCopy() *NodeResourcesFitArgs { + if in == nil { + return nil + } + out := new(NodeResourcesFitArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeResourcesFitArgs) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Plugin) DeepCopyInto(out *Plugin) { + *out = *in + if in.Weight != nil { + in, out := &in.Weight, &out.Weight + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Plugin. +func (in *Plugin) DeepCopy() *Plugin { + if in == nil { + return nil + } + out := new(Plugin) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PluginConfig) DeepCopyInto(out *PluginConfig) { + *out = *in + in.Args.DeepCopyInto(&out.Args) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PluginConfig. +func (in *PluginConfig) DeepCopy() *PluginConfig { + if in == nil { + return nil + } + out := new(PluginConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PluginSet) DeepCopyInto(out *PluginSet) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = make([]Plugin, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Disabled != nil { + in, out := &in.Disabled, &out.Disabled + *out = make([]Plugin, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PluginSet. +func (in *PluginSet) DeepCopy() *PluginSet { + if in == nil { + return nil + } + out := new(PluginSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Plugins) DeepCopyInto(out *Plugins) { + *out = *in + in.QueueSort.DeepCopyInto(&out.QueueSort) + in.PreFilter.DeepCopyInto(&out.PreFilter) + in.Filter.DeepCopyInto(&out.Filter) + in.PostFilter.DeepCopyInto(&out.PostFilter) + in.PreScore.DeepCopyInto(&out.PreScore) + in.Score.DeepCopyInto(&out.Score) + in.Reserve.DeepCopyInto(&out.Reserve) + in.Permit.DeepCopyInto(&out.Permit) + in.PreBind.DeepCopyInto(&out.PreBind) + in.Bind.DeepCopyInto(&out.Bind) + in.PostBind.DeepCopyInto(&out.PostBind) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Plugins. +func (in *Plugins) DeepCopy() *Plugins { + if in == nil { + return nil + } + out := new(Plugins) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodTopologySpreadArgs) DeepCopyInto(out *PodTopologySpreadArgs) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.DefaultConstraints != nil { + in, out := &in.DefaultConstraints, &out.DefaultConstraints + *out = make([]corev1.TopologySpreadConstraint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodTopologySpreadArgs. +func (in *PodTopologySpreadArgs) DeepCopy() *PodTopologySpreadArgs { + if in == nil { + return nil + } + out := new(PodTopologySpreadArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PodTopologySpreadArgs) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RequestedToCapacityRatioParam) DeepCopyInto(out *RequestedToCapacityRatioParam) { + *out = *in + if in.Shape != nil { + in, out := &in.Shape, &out.Shape + *out = make([]UtilizationShapePoint, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestedToCapacityRatioParam. +func (in *RequestedToCapacityRatioParam) DeepCopy() *RequestedToCapacityRatioParam { + if in == nil { + return nil + } + out := new(RequestedToCapacityRatioParam) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceSpec) DeepCopyInto(out *ResourceSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceSpec. +func (in *ResourceSpec) DeepCopy() *ResourceSpec { + if in == nil { + return nil + } + out := new(ResourceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScoringStrategy) DeepCopyInto(out *ScoringStrategy) { + *out = *in + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]ResourceSpec, len(*in)) + copy(*out, *in) + } + if in.RequestedToCapacityRatio != nil { + in, out := &in.RequestedToCapacityRatio, &out.RequestedToCapacityRatio + *out = new(RequestedToCapacityRatioParam) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScoringStrategy. +func (in *ScoringStrategy) DeepCopy() *ScoringStrategy { + if in == nil { + return nil + } + out := new(ScoringStrategy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UtilizationShapePoint) DeepCopyInto(out *UtilizationShapePoint) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UtilizationShapePoint. +func (in *UtilizationShapePoint) DeepCopy() *UtilizationShapePoint { + if in == nil { + return nil + } + out := new(UtilizationShapePoint) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeBindingArgs) DeepCopyInto(out *VolumeBindingArgs) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.BindTimeoutSeconds != nil { + in, out := &in.BindTimeoutSeconds, &out.BindTimeoutSeconds + *out = new(int64) + **out = **in + } + if in.Shape != nil { + in, out := &in.Shape, &out.Shape + *out = make([]UtilizationShapePoint, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeBindingArgs. +func (in *VolumeBindingArgs) DeepCopy() *VolumeBindingArgs { + if in == nil { + return nil + } + out := new(VolumeBindingArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeBindingArgs) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} From a07022ae8a4a968a83643030a02634be64087a81 Mon Sep 17 00:00:00 2001 From: ravisantoshgudimetla Date: Mon, 9 Aug 2021 15:48:33 -0400 Subject: [PATCH 2/5] [cc][api]: Introduce scheduler v1beta3 api Changes in pkg/apis/scheduler reflecting the changes from staging. The weights of following priority plugins were increased: - TaintTolerations - NodeAffinity - InterPodAffinity as they're user facing priorities and they should be more influential when compared to default plugins which don't have any user say. xref: https://github.com/kubernetes/enhancements/pull/2850 --- .../apis/config/v1beta3/conversion.go | 107 +++ .../apis/config/v1beta3/default_plugins.go | 201 ++++ .../config/v1beta3/default_plugins_test.go | 464 ++++++++++ pkg/scheduler/apis/config/v1beta3/defaults.go | 257 ++++++ .../apis/config/v1beta3/defaults_test.go | 698 ++++++++++++++ pkg/scheduler/apis/config/v1beta3/doc.go | 24 + pkg/scheduler/apis/config/v1beta3/register.go | 42 + .../config/v1beta3/zz_generated.conversion.go | 859 ++++++++++++++++++ .../config/v1beta3/zz_generated.deepcopy.go | 22 + .../config/v1beta3/zz_generated.defaults.go | 73 ++ 10 files changed, 2747 insertions(+) create mode 100644 pkg/scheduler/apis/config/v1beta3/conversion.go create mode 100644 pkg/scheduler/apis/config/v1beta3/default_plugins.go create mode 100644 pkg/scheduler/apis/config/v1beta3/default_plugins_test.go create mode 100644 pkg/scheduler/apis/config/v1beta3/defaults.go create mode 100644 pkg/scheduler/apis/config/v1beta3/defaults_test.go create mode 100644 pkg/scheduler/apis/config/v1beta3/doc.go create mode 100644 pkg/scheduler/apis/config/v1beta3/register.go create mode 100644 pkg/scheduler/apis/config/v1beta3/zz_generated.conversion.go create mode 100644 pkg/scheduler/apis/config/v1beta3/zz_generated.deepcopy.go create mode 100644 pkg/scheduler/apis/config/v1beta3/zz_generated.defaults.go diff --git a/pkg/scheduler/apis/config/v1beta3/conversion.go b/pkg/scheduler/apis/config/v1beta3/conversion.go new file mode 100644 index 0000000000000..e37daf09c5562 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta3/conversion.go @@ -0,0 +1,107 @@ +/* +Copyright 2021 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. +*/ + +package v1beta3 + +import ( + "fmt" + "sync" + + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/kube-scheduler/config/v1beta3" + "k8s.io/kubernetes/pkg/scheduler/apis/config" +) + +var ( + // pluginArgConversionScheme is a scheme with internal and v1beta3 registered, + // used for defaulting/converting typed PluginConfig Args. + // Access via getPluginArgConversionScheme() + pluginArgConversionScheme *runtime.Scheme + initPluginArgConversionScheme sync.Once +) + +func GetPluginArgConversionScheme() *runtime.Scheme { + initPluginArgConversionScheme.Do(func() { + // set up the scheme used for plugin arg conversion + pluginArgConversionScheme = runtime.NewScheme() + utilruntime.Must(AddToScheme(pluginArgConversionScheme)) + utilruntime.Must(config.AddToScheme(pluginArgConversionScheme)) + }) + return pluginArgConversionScheme +} + +func Convert_v1beta3_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(in *v1beta3.KubeSchedulerConfiguration, out *config.KubeSchedulerConfiguration, s conversion.Scope) error { + if err := autoConvert_v1beta3_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(in, out, s); err != nil { + return err + } + return convertToInternalPluginConfigArgs(out) +} + +// convertToInternalPluginConfigArgs converts PluginConfig#Args into internal +// types using a scheme, after applying defaults. +func convertToInternalPluginConfigArgs(out *config.KubeSchedulerConfiguration) error { + scheme := GetPluginArgConversionScheme() + for i := range out.Profiles { + prof := &out.Profiles[i] + for j := range prof.PluginConfig { + args := prof.PluginConfig[j].Args + if args == nil { + continue + } + if _, isUnknown := args.(*runtime.Unknown); isUnknown { + continue + } + internalArgs, err := scheme.ConvertToVersion(args, config.SchemeGroupVersion) + if err != nil { + return fmt.Errorf("converting .Profiles[%d].PluginConfig[%d].Args into internal type: %w", i, j, err) + } + prof.PluginConfig[j].Args = internalArgs + } + } + return nil +} + +func Convert_config_KubeSchedulerConfiguration_To_v1beta3_KubeSchedulerConfiguration(in *config.KubeSchedulerConfiguration, out *v1beta3.KubeSchedulerConfiguration, s conversion.Scope) error { + if err := autoConvert_config_KubeSchedulerConfiguration_To_v1beta3_KubeSchedulerConfiguration(in, out, s); err != nil { + return err + } + return convertToExternalPluginConfigArgs(out) +} + +// convertToExternalPluginConfigArgs converts PluginConfig#Args into +// external (versioned) types using a scheme. +func convertToExternalPluginConfigArgs(out *v1beta3.KubeSchedulerConfiguration) error { + scheme := GetPluginArgConversionScheme() + for i := range out.Profiles { + for j := range out.Profiles[i].PluginConfig { + args := out.Profiles[i].PluginConfig[j].Args + if args.Object == nil { + continue + } + if _, isUnknown := args.Object.(*runtime.Unknown); isUnknown { + continue + } + externalArgs, err := scheme.ConvertToVersion(args.Object, SchemeGroupVersion) + if err != nil { + return err + } + out.Profiles[i].PluginConfig[j].Args.Object = externalArgs + } + } + return nil +} diff --git a/pkg/scheduler/apis/config/v1beta3/default_plugins.go b/pkg/scheduler/apis/config/v1beta3/default_plugins.go new file mode 100644 index 0000000000000..3d4f35e2f164d --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta3/default_plugins.go @@ -0,0 +1,201 @@ +/* +Copyright 2021 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. +*/ + +package v1beta3 + +import ( + "k8s.io/apimachinery/pkg/util/sets" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/klog/v2" + "k8s.io/kube-scheduler/config/v1beta3" + "k8s.io/kubernetes/pkg/features" + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/names" + "k8s.io/utils/pointer" +) + +// getDefaultPlugins returns the default set of plugins. +func getDefaultPlugins() *v1beta3.Plugins { + plugins := &v1beta3.Plugins{ + QueueSort: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.PrioritySort}, + }, + }, + PreFilter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.NodeResourcesFit}, + {Name: names.NodePorts}, + {Name: names.VolumeRestrictions}, + {Name: names.PodTopologySpread}, + {Name: names.InterPodAffinity}, + {Name: names.VolumeBinding}, + {Name: names.NodeAffinity}, + }, + }, + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.NodeUnschedulable}, + {Name: names.NodeName}, + {Name: names.TaintToleration}, + {Name: names.NodeAffinity}, + {Name: names.NodePorts}, + {Name: names.NodeResourcesFit}, + {Name: names.VolumeRestrictions}, + {Name: names.EBSLimits}, + {Name: names.GCEPDLimits}, + {Name: names.NodeVolumeLimits}, + {Name: names.AzureDiskLimits}, + {Name: names.VolumeBinding}, + {Name: names.VolumeZone}, + {Name: names.PodTopologySpread}, + {Name: names.InterPodAffinity}, + }, + }, + PostFilter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.DefaultPreemption}, + }, + }, + PreScore: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.InterPodAffinity}, + {Name: names.PodTopologySpread}, + {Name: names.TaintToleration}, + {Name: names.NodeAffinity}, + }, + }, + Score: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32Ptr(1)}, + {Name: names.ImageLocality, Weight: pointer.Int32Ptr(1)}, + {Name: names.NodeResourcesFit, Weight: pointer.Int32Ptr(1)}, + // Weight is doubled because: + // - This is a score coming from user preference. + {Name: names.InterPodAffinity, Weight: pointer.Int32Ptr(2)}, + // Weight is doubled because: + // - This is a score coming from user preference. + {Name: names.NodeAffinity, Weight: pointer.Int32Ptr(2)}, + // Weight is doubled because: + // - This is a score coming from user preference. + // - It makes its signal comparable to NodeResourcesFit.LeastAllocated. + {Name: names.PodTopologySpread, Weight: pointer.Int32Ptr(2)}, + // Weight is tripled because: + // - This is a score coming from user preference. + // - Usage of node tainting to group nodes in the cluster is becoming a valid use-case more often + // for many user workloads + {Name: names.TaintToleration, Weight: pointer.Int32Ptr(3)}, + }, + }, + Reserve: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.VolumeBinding}, + }, + }, + PreBind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.VolumeBinding}, + }, + }, + Bind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.DefaultBinder}, + }, + }, + } + applyFeatureGates(plugins) + + return plugins +} + +func applyFeatureGates(config *v1beta3.Plugins) { + if utilfeature.DefaultFeatureGate.Enabled(features.VolumeCapacityPriority) { + config.Score.Enabled = append(config.Score.Enabled, v1beta3.Plugin{Name: names.VolumeBinding, Weight: pointer.Int32Ptr(1)}) + } + + if !utilfeature.DefaultFeatureGate.Enabled(features.DefaultPodTopologySpread) { + // When feature is enabled, the default spreading is done by + // PodTopologySpread plugin, which is enabled by default. + klog.InfoS("Registering SelectorSpread plugin") + s := v1beta3.Plugin{Name: names.SelectorSpread} + config.PreScore.Enabled = append(config.PreScore.Enabled, s) + s.Weight = pointer.Int32Ptr(1) + config.Score.Enabled = append(config.Score.Enabled, s) + } +} + +// mergePlugins merges the custom set into the given default one, handling disabled sets. +func mergePlugins(defaultPlugins, customPlugins *v1beta3.Plugins) *v1beta3.Plugins { + if customPlugins == nil { + return defaultPlugins + } + + defaultPlugins.QueueSort = mergePluginSet(defaultPlugins.QueueSort, customPlugins.QueueSort) + defaultPlugins.PreFilter = mergePluginSet(defaultPlugins.PreFilter, customPlugins.PreFilter) + defaultPlugins.Filter = mergePluginSet(defaultPlugins.Filter, customPlugins.Filter) + defaultPlugins.PostFilter = mergePluginSet(defaultPlugins.PostFilter, customPlugins.PostFilter) + defaultPlugins.PreScore = mergePluginSet(defaultPlugins.PreScore, customPlugins.PreScore) + defaultPlugins.Score = mergePluginSet(defaultPlugins.Score, customPlugins.Score) + defaultPlugins.Reserve = mergePluginSet(defaultPlugins.Reserve, customPlugins.Reserve) + defaultPlugins.Permit = mergePluginSet(defaultPlugins.Permit, customPlugins.Permit) + defaultPlugins.PreBind = mergePluginSet(defaultPlugins.PreBind, customPlugins.PreBind) + defaultPlugins.Bind = mergePluginSet(defaultPlugins.Bind, customPlugins.Bind) + defaultPlugins.PostBind = mergePluginSet(defaultPlugins.PostBind, customPlugins.PostBind) + return defaultPlugins +} + +type pluginIndex struct { + index int + plugin v1beta3.Plugin +} + +func mergePluginSet(defaultPluginSet, customPluginSet v1beta3.PluginSet) v1beta3.PluginSet { + disabledPlugins := sets.NewString() + enabledCustomPlugins := make(map[string]pluginIndex) + // replacedPluginIndex is a set of index of plugins, which have replaced the default plugins. + replacedPluginIndex := sets.NewInt() + for _, disabledPlugin := range customPluginSet.Disabled { + disabledPlugins.Insert(disabledPlugin.Name) + } + for index, enabledPlugin := range customPluginSet.Enabled { + enabledCustomPlugins[enabledPlugin.Name] = pluginIndex{index, enabledPlugin} + } + var enabledPlugins []v1beta3.Plugin + if !disabledPlugins.Has("*") { + for _, defaultEnabledPlugin := range defaultPluginSet.Enabled { + if disabledPlugins.Has(defaultEnabledPlugin.Name) { + continue + } + // The default plugin is explicitly re-configured, update the default plugin accordingly. + if customPlugin, ok := enabledCustomPlugins[defaultEnabledPlugin.Name]; ok { + klog.InfoS("Default plugin is explicitly re-configured; overriding", "plugin", defaultEnabledPlugin.Name) + // Update the default plugin in place to preserve order. + defaultEnabledPlugin = customPlugin.plugin + replacedPluginIndex.Insert(customPlugin.index) + } + enabledPlugins = append(enabledPlugins, defaultEnabledPlugin) + } + } + + // Append all the custom plugins which haven't replaced any default plugins. + // Note: duplicated custom plugins will still be appended here. + // If so, the instantiation of scheduler framework will detect it and abort. + for index, plugin := range customPluginSet.Enabled { + if !replacedPluginIndex.Has(index) { + enabledPlugins = append(enabledPlugins, plugin) + } + } + return v1beta3.PluginSet{Enabled: enabledPlugins} +} diff --git a/pkg/scheduler/apis/config/v1beta3/default_plugins_test.go b/pkg/scheduler/apis/config/v1beta3/default_plugins_test.go new file mode 100644 index 0000000000000..56cdbe366c303 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta3/default_plugins_test.go @@ -0,0 +1,464 @@ +/* +Copyright 2017 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. +*/ + +package v1beta3 + +import ( + "k8s.io/kube-scheduler/config/v1beta3" + "testing" + + "github.com/google/go-cmp/cmp" + "k8s.io/apiserver/pkg/util/feature" + "k8s.io/component-base/featuregate" + featuregatetesting "k8s.io/component-base/featuregate/testing" + "k8s.io/kubernetes/pkg/features" + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/names" + "k8s.io/utils/pointer" +) + +func TestApplyFeatureGates(t *testing.T) { + tests := []struct { + name string + features map[featuregate.Feature]bool + wantConfig *v1beta3.Plugins + }{ + { + name: "Feature gates disabled", + wantConfig: &v1beta3.Plugins{ + QueueSort: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.PrioritySort}, + }, + }, + PreFilter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.NodeResourcesFit}, + {Name: names.NodePorts}, + {Name: names.VolumeRestrictions}, + {Name: names.PodTopologySpread}, + {Name: names.InterPodAffinity}, + {Name: names.VolumeBinding}, + {Name: names.NodeAffinity}, + }, + }, + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.NodeUnschedulable}, + {Name: names.NodeName}, + {Name: names.TaintToleration}, + {Name: names.NodeAffinity}, + {Name: names.NodePorts}, + {Name: names.NodeResourcesFit}, + {Name: names.VolumeRestrictions}, + {Name: names.EBSLimits}, + {Name: names.GCEPDLimits}, + {Name: names.NodeVolumeLimits}, + {Name: names.AzureDiskLimits}, + {Name: names.VolumeBinding}, + {Name: names.VolumeZone}, + {Name: names.PodTopologySpread}, + {Name: names.InterPodAffinity}, + }, + }, + PostFilter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.DefaultPreemption}, + }, + }, + PreScore: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.InterPodAffinity}, + {Name: names.PodTopologySpread}, + {Name: names.TaintToleration}, + {Name: names.NodeAffinity}, + }, + }, + Score: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32Ptr(1)}, + {Name: names.ImageLocality, Weight: pointer.Int32Ptr(1)}, + {Name: names.NodeResourcesFit, Weight: pointer.Int32Ptr(1)}, + {Name: names.InterPodAffinity, Weight: pointer.Int32Ptr(2)}, + {Name: names.NodeAffinity, Weight: pointer.Int32Ptr(2)}, + {Name: names.PodTopologySpread, Weight: pointer.Int32Ptr(2)}, + {Name: names.TaintToleration, Weight: pointer.Int32Ptr(3)}, + }, + }, + Reserve: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.VolumeBinding}, + }, + }, + PreBind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.VolumeBinding}, + }, + }, + Bind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.DefaultBinder}, + }, + }, + }, + }, + { + name: "DefaultPodTopologySpread disabled", + features: map[featuregate.Feature]bool{ + features.DefaultPodTopologySpread: false, + }, + wantConfig: &v1beta3.Plugins{ + QueueSort: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.PrioritySort}, + }, + }, + PreFilter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.NodeResourcesFit}, + {Name: names.NodePorts}, + {Name: names.VolumeRestrictions}, + {Name: names.PodTopologySpread}, + {Name: names.InterPodAffinity}, + {Name: names.VolumeBinding}, + {Name: names.NodeAffinity}, + }, + }, + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.NodeUnschedulable}, + {Name: names.NodeName}, + {Name: names.TaintToleration}, + {Name: names.NodeAffinity}, + {Name: names.NodePorts}, + {Name: names.NodeResourcesFit}, + {Name: names.VolumeRestrictions}, + {Name: names.EBSLimits}, + {Name: names.GCEPDLimits}, + {Name: names.NodeVolumeLimits}, + {Name: names.AzureDiskLimits}, + {Name: names.VolumeBinding}, + {Name: names.VolumeZone}, + {Name: names.PodTopologySpread}, + {Name: names.InterPodAffinity}, + }, + }, + PostFilter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.DefaultPreemption}, + }, + }, + PreScore: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.InterPodAffinity}, + {Name: names.PodTopologySpread}, + {Name: names.TaintToleration}, + {Name: names.NodeAffinity}, + {Name: names.SelectorSpread}, + }, + }, + Score: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32Ptr(1)}, + {Name: names.ImageLocality, Weight: pointer.Int32Ptr(1)}, + {Name: names.NodeResourcesFit, Weight: pointer.Int32Ptr(1)}, + {Name: names.InterPodAffinity, Weight: pointer.Int32Ptr(2)}, + {Name: names.NodeAffinity, Weight: pointer.Int32Ptr(2)}, + {Name: names.PodTopologySpread, Weight: pointer.Int32Ptr(2)}, + {Name: names.TaintToleration, Weight: pointer.Int32Ptr(3)}, + {Name: names.SelectorSpread, Weight: pointer.Int32Ptr(1)}, + }, + }, + Reserve: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.VolumeBinding}, + }, + }, + PreBind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.VolumeBinding}, + }, + }, + Bind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.DefaultBinder}, + }, + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + for k, v := range test.features { + defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, k, v)() + } + + gotConfig := getDefaultPlugins() + if diff := cmp.Diff(test.wantConfig, gotConfig); diff != "" { + t.Errorf("unexpected config diff (-want, +got): %s", diff) + } + }) + } +} + +func TestMergePlugins(t *testing.T) { + tests := []struct { + name string + customPlugins *v1beta3.Plugins + defaultPlugins *v1beta3.Plugins + expectedPlugins *v1beta3.Plugins + }{ + { + name: "AppendCustomPlugin", + customPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "CustomPlugin"}, + }, + }, + }, + defaultPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "DefaultPlugin1"}, + {Name: "DefaultPlugin2"}, + }, + }, + }, + expectedPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "DefaultPlugin1"}, + {Name: "DefaultPlugin2"}, + {Name: "CustomPlugin"}, + }, + }, + }, + }, + { + name: "InsertAfterDefaultPlugins2", + customPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "CustomPlugin"}, + {Name: "DefaultPlugin2"}, + }, + Disabled: []v1beta3.Plugin{ + {Name: "DefaultPlugin2"}, + }, + }, + }, + defaultPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "DefaultPlugin1"}, + {Name: "DefaultPlugin2"}, + }, + }, + }, + expectedPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "DefaultPlugin1"}, + {Name: "CustomPlugin"}, + {Name: "DefaultPlugin2"}, + }, + }, + }, + }, + { + name: "InsertBeforeAllPlugins", + customPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "CustomPlugin"}, + {Name: "DefaultPlugin1"}, + {Name: "DefaultPlugin2"}, + }, + Disabled: []v1beta3.Plugin{ + {Name: "*"}, + }, + }, + }, + defaultPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "DefaultPlugin1"}, + {Name: "DefaultPlugin2"}, + }, + }, + }, + expectedPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "CustomPlugin"}, + {Name: "DefaultPlugin1"}, + {Name: "DefaultPlugin2"}, + }, + }, + }, + }, + { + name: "ReorderDefaultPlugins", + customPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "DefaultPlugin2"}, + {Name: "DefaultPlugin1"}, + }, + Disabled: []v1beta3.Plugin{ + {Name: "*"}, + }, + }, + }, + defaultPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "DefaultPlugin1"}, + {Name: "DefaultPlugin2"}, + }, + }, + }, + expectedPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "DefaultPlugin2"}, + {Name: "DefaultPlugin1"}, + }, + }, + }, + }, + { + name: "ApplyNilCustomPlugin", + customPlugins: nil, + defaultPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "DefaultPlugin1"}, + {Name: "DefaultPlugin2"}, + }, + }, + }, + expectedPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "DefaultPlugin1"}, + {Name: "DefaultPlugin2"}, + }, + }, + }, + }, + { + name: "CustomPluginOverrideDefaultPlugin", + customPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "Plugin1", Weight: pointer.Int32Ptr(2)}, + {Name: "Plugin3", Weight: pointer.Int32Ptr(3)}, + }, + }, + }, + defaultPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "Plugin1"}, + {Name: "Plugin2"}, + {Name: "Plugin3"}, + }, + }, + }, + expectedPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "Plugin1", Weight: pointer.Int32Ptr(2)}, + {Name: "Plugin2"}, + {Name: "Plugin3", Weight: pointer.Int32Ptr(3)}, + }, + }, + }, + }, + { + name: "OrderPreserveAfterOverride", + customPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "Plugin2", Weight: pointer.Int32Ptr(2)}, + {Name: "Plugin1", Weight: pointer.Int32Ptr(1)}, + }, + }, + }, + defaultPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "Plugin1"}, + {Name: "Plugin2"}, + {Name: "Plugin3"}, + }, + }, + }, + expectedPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "Plugin1", Weight: pointer.Int32Ptr(1)}, + {Name: "Plugin2", Weight: pointer.Int32Ptr(2)}, + {Name: "Plugin3"}, + }, + }, + }, + }, + { + name: "RepeatedCustomPlugin", + customPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "Plugin1"}, + {Name: "Plugin2", Weight: pointer.Int32Ptr(2)}, + {Name: "Plugin3"}, + {Name: "Plugin2", Weight: pointer.Int32Ptr(4)}, + }, + }, + }, + defaultPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "Plugin1"}, + {Name: "Plugin2"}, + {Name: "Plugin3"}, + }, + }, + }, + expectedPlugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "Plugin1"}, + {Name: "Plugin2", Weight: pointer.Int32Ptr(4)}, + {Name: "Plugin3"}, + {Name: "Plugin2", Weight: pointer.Int32Ptr(2)}, + }, + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + test.defaultPlugins = mergePlugins(test.defaultPlugins, test.customPlugins) + if d := cmp.Diff(test.expectedPlugins, test.defaultPlugins); d != "" { + t.Fatalf("plugins mismatch (-want +got):\n%s", d) + } + }) + } +} diff --git a/pkg/scheduler/apis/config/v1beta3/defaults.go b/pkg/scheduler/apis/config/v1beta3/defaults.go new file mode 100644 index 0000000000000..cd2929a541b4f --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta3/defaults.go @@ -0,0 +1,257 @@ +/* +Copyright 2021 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. +*/ + +package v1beta3 + +import ( + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apiserver/pkg/util/feature" + componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1" + "k8s.io/kube-scheduler/config/v1beta3" + "k8s.io/kubernetes/pkg/features" + "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/utils/pointer" +) + +var defaultResourceSpec = []v1beta3.ResourceSpec{ + {Name: string(v1.ResourceCPU), Weight: 1}, + {Name: string(v1.ResourceMemory), Weight: 1}, +} + +func addDefaultingFuncs(scheme *runtime.Scheme) error { + return RegisterDefaults(scheme) +} + +func pluginsNames(p *v1beta3.Plugins) []string { + if p == nil { + return nil + } + extensions := []v1beta3.PluginSet{ + p.PreFilter, + p.Filter, + p.PostFilter, + p.Reserve, + p.PreScore, + p.Score, + p.PreBind, + p.Bind, + p.PostBind, + p.Permit, + p.QueueSort, + } + n := sets.NewString() + for _, e := range extensions { + for _, pg := range e.Enabled { + n.Insert(pg.Name) + } + } + return n.List() +} + +func setDefaults_KubeSchedulerProfile(prof *v1beta3.KubeSchedulerProfile) { + // Set default plugins. + prof.Plugins = mergePlugins(getDefaultPlugins(), prof.Plugins) + + // Set default plugin configs. + scheme := GetPluginArgConversionScheme() + existingConfigs := sets.NewString() + for j := range prof.PluginConfig { + existingConfigs.Insert(prof.PluginConfig[j].Name) + args := prof.PluginConfig[j].Args.Object + if _, isUnknown := args.(*runtime.Unknown); isUnknown { + continue + } + scheme.Default(args) + } + + // Append default configs for plugins that didn't have one explicitly set. + for _, name := range pluginsNames(prof.Plugins) { + if existingConfigs.Has(name) { + continue + } + gvk := v1beta3.SchemeGroupVersion.WithKind(name + "Args") + args, err := scheme.New(gvk) + if err != nil { + // This plugin is out-of-tree or doesn't require configuration. + continue + } + scheme.Default(args) + args.GetObjectKind().SetGroupVersionKind(gvk) + prof.PluginConfig = append(prof.PluginConfig, v1beta3.PluginConfig{ + Name: name, + Args: runtime.RawExtension{Object: args}, + }) + } +} + +// SetDefaults_KubeSchedulerConfiguration sets additional defaults +func SetDefaults_KubeSchedulerConfiguration(obj *v1beta3.KubeSchedulerConfiguration) { + if obj.Parallelism == nil { + obj.Parallelism = pointer.Int32Ptr(16) + } + + if len(obj.Profiles) == 0 { + obj.Profiles = append(obj.Profiles, v1beta3.KubeSchedulerProfile{}) + } + // Only apply a default scheduler name when there is a single profile. + // Validation will ensure that every profile has a non-empty unique name. + if len(obj.Profiles) == 1 && obj.Profiles[0].SchedulerName == nil { + obj.Profiles[0].SchedulerName = pointer.StringPtr(v1.DefaultSchedulerName) + } + + // Add the default set of plugins and apply the configuration. + for i := range obj.Profiles { + prof := &obj.Profiles[i] + setDefaults_KubeSchedulerProfile(prof) + } + + if obj.PercentageOfNodesToScore == nil { + percentageOfNodesToScore := int32(config.DefaultPercentageOfNodesToScore) + obj.PercentageOfNodesToScore = &percentageOfNodesToScore + } + + if len(obj.LeaderElection.ResourceLock) == 0 { + // Use lease-based leader election to reduce cost. + // We migrated for EndpointsLease lock in 1.17 and starting in 1.20 we + // migrated to Lease lock. + obj.LeaderElection.ResourceLock = "leases" + } + if len(obj.LeaderElection.ResourceNamespace) == 0 { + obj.LeaderElection.ResourceNamespace = v1beta3.SchedulerDefaultLockObjectNamespace + } + if len(obj.LeaderElection.ResourceName) == 0 { + obj.LeaderElection.ResourceName = v1beta3.SchedulerDefaultLockObjectName + } + + if len(obj.ClientConnection.ContentType) == 0 { + obj.ClientConnection.ContentType = "application/vnd.kubernetes.protobuf" + } + // Scheduler has an opinion about QPS/Burst, setting specific defaults for itself, instead of generic settings. + if obj.ClientConnection.QPS == 0.0 { + obj.ClientConnection.QPS = 50.0 + } + if obj.ClientConnection.Burst == 0 { + obj.ClientConnection.Burst = 100 + } + + // Use the default LeaderElectionConfiguration options + componentbaseconfigv1alpha1.RecommendedDefaultLeaderElectionConfiguration(&obj.LeaderElection) + + if obj.PodInitialBackoffSeconds == nil { + val := int64(1) + obj.PodInitialBackoffSeconds = &val + } + + if obj.PodMaxBackoffSeconds == nil { + val := int64(10) + obj.PodMaxBackoffSeconds = &val + } + + // Enable profiling by default in the scheduler + if obj.EnableProfiling == nil { + enableProfiling := true + obj.EnableProfiling = &enableProfiling + } + + // Enable contention profiling by default if profiling is enabled + if *obj.EnableProfiling && obj.EnableContentionProfiling == nil { + enableContentionProfiling := true + obj.EnableContentionProfiling = &enableContentionProfiling + } +} + +func SetDefaults_DefaultPreemptionArgs(obj *v1beta3.DefaultPreemptionArgs) { + if obj.MinCandidateNodesPercentage == nil { + obj.MinCandidateNodesPercentage = pointer.Int32Ptr(10) + } + if obj.MinCandidateNodesAbsolute == nil { + obj.MinCandidateNodesAbsolute = pointer.Int32Ptr(100) + } +} + +func SetDefaults_InterPodAffinityArgs(obj *v1beta3.InterPodAffinityArgs) { + // Note that an object is created manually in cmd/kube-scheduler/app/options/deprecated.go + // DeprecatedOptions#ApplyTo. + // Update that object if a new default field is added here. + if obj.HardPodAffinityWeight == nil { + obj.HardPodAffinityWeight = pointer.Int32Ptr(1) + } +} + +func SetDefaults_VolumeBindingArgs(obj *v1beta3.VolumeBindingArgs) { + if obj.BindTimeoutSeconds == nil { + obj.BindTimeoutSeconds = pointer.Int64Ptr(600) + } + if len(obj.Shape) == 0 && feature.DefaultFeatureGate.Enabled(features.VolumeCapacityPriority) { + obj.Shape = []v1beta3.UtilizationShapePoint{ + { + Utilization: 0, + Score: 0, + }, + { + Utilization: 100, + Score: int32(config.MaxCustomPriorityScore), + }, + } + } +} + +func SetDefaults_NodeResourcesBalancedAllocationArgs(obj *v1beta3.NodeResourcesBalancedAllocationArgs) { + if len(obj.Resources) == 0 { + obj.Resources = append(obj.Resources, + v1beta3.ResourceSpec{Name: string(v1.ResourceCPU), Weight: 1}, + v1beta3.ResourceSpec{Name: string(v1.ResourceMemory), Weight: 1}, + ) + } + // If the weight is not set or it is explicitly set to 0, then apply the default weight(1) instead. + for i := range obj.Resources { + if obj.Resources[i].Weight == 0 { + obj.Resources[i].Weight = 1 + } + } +} + +func SetDefaults_PodTopologySpreadArgs(obj *v1beta3.PodTopologySpreadArgs) { + if feature.DefaultFeatureGate.Enabled(features.DefaultPodTopologySpread) { + if obj.DefaultingType == "" { + obj.DefaultingType = v1beta3.SystemDefaulting + } + return + } + if obj.DefaultingType == "" { + obj.DefaultingType = v1beta3.ListDefaulting + } +} + +func SetDefaults_NodeResourcesFitArgs(obj *v1beta3.NodeResourcesFitArgs) { + if obj.ScoringStrategy == nil { + obj.ScoringStrategy = &v1beta3.ScoringStrategy{ + Type: v1beta3.ScoringStrategyType(config.LeastAllocated), + Resources: defaultResourceSpec, + } + } + if len(obj.ScoringStrategy.Resources) == 0 { + // If no resources specified, use the default set. + obj.ScoringStrategy.Resources = append(obj.ScoringStrategy.Resources, defaultResourceSpec...) + } + for i := range obj.ScoringStrategy.Resources { + if obj.ScoringStrategy.Resources[i].Weight == 0 { + obj.ScoringStrategy.Resources[i].Weight = 1 + } + } +} diff --git a/pkg/scheduler/apis/config/v1beta3/defaults_test.go b/pkg/scheduler/apis/config/v1beta3/defaults_test.go new file mode 100644 index 0000000000000..d0cb48b40d587 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta3/defaults_test.go @@ -0,0 +1,698 @@ +/* +Copyright 2021 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. +*/ + +package v1beta3 + +import ( + "testing" + "time" + + "github.com/google/go-cmp/cmp" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apiserver/pkg/util/feature" + componentbaseconfig "k8s.io/component-base/config/v1alpha1" + "k8s.io/component-base/featuregate" + featuregatetesting "k8s.io/component-base/featuregate/testing" + "k8s.io/kube-scheduler/config/v1beta3" + "k8s.io/kubernetes/pkg/features" + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/names" + "k8s.io/utils/pointer" +) + +var pluginConfigs = []v1beta3.PluginConfig{ + { + Name: "DefaultPreemption", + Args: runtime.RawExtension{ + Object: &v1beta3.DefaultPreemptionArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "DefaultPreemptionArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + MinCandidateNodesPercentage: pointer.Int32Ptr(10), + MinCandidateNodesAbsolute: pointer.Int32Ptr(100), + }}, + }, + { + Name: "InterPodAffinity", + Args: runtime.RawExtension{ + Object: &v1beta3.InterPodAffinityArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "InterPodAffinityArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + HardPodAffinityWeight: pointer.Int32Ptr(1), + }}, + }, + { + Name: "NodeAffinity", + Args: runtime.RawExtension{Object: &v1beta3.NodeAffinityArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "NodeAffinityArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + }}, + }, + { + Name: "NodeResourcesBalancedAllocation", + Args: runtime.RawExtension{Object: &v1beta3.NodeResourcesBalancedAllocationArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "NodeResourcesBalancedAllocationArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + Resources: []v1beta3.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }}, + }, + { + Name: "NodeResourcesFit", + Args: runtime.RawExtension{Object: &v1beta3.NodeResourcesFitArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "NodeResourcesFitArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + ScoringStrategy: &v1beta3.ScoringStrategy{ + Type: v1beta3.LeastAllocated, + Resources: []v1beta3.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }, + }}, + }, + { + Name: "PodTopologySpread", + Args: runtime.RawExtension{Object: &v1beta3.PodTopologySpreadArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "PodTopologySpreadArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + DefaultingType: v1beta3.SystemDefaulting, + }}, + }, + { + Name: "VolumeBinding", + Args: runtime.RawExtension{Object: &v1beta3.VolumeBindingArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "VolumeBindingArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + BindTimeoutSeconds: pointer.Int64Ptr(600), + }}, + }, +} + +func TestSchedulerDefaults(t *testing.T) { + enable := true + tests := []struct { + name string + config *v1beta3.KubeSchedulerConfiguration + expected *v1beta3.KubeSchedulerConfiguration + }{ + { + name: "empty config", + config: &v1beta3.KubeSchedulerConfiguration{}, + expected: &v1beta3.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ + EnableProfiling: &enable, + EnableContentionProfiling: &enable, + }, + LeaderElection: componentbaseconfig.LeaderElectionConfiguration{ + LeaderElect: pointer.BoolPtr(true), + LeaseDuration: metav1.Duration{Duration: 15 * time.Second}, + RenewDeadline: metav1.Duration{Duration: 10 * time.Second}, + RetryPeriod: metav1.Duration{Duration: 2 * time.Second}, + ResourceLock: "leases", + ResourceNamespace: "kube-system", + ResourceName: "kube-scheduler", + }, + ClientConnection: componentbaseconfig.ClientConnectionConfiguration{ + QPS: 50, + Burst: 100, + ContentType: "application/vnd.kubernetes.protobuf", + }, + PercentageOfNodesToScore: pointer.Int32Ptr(0), + PodInitialBackoffSeconds: pointer.Int64Ptr(1), + PodMaxBackoffSeconds: pointer.Int64Ptr(10), + Profiles: []v1beta3.KubeSchedulerProfile{ + { + Plugins: getDefaultPlugins(), + PluginConfig: pluginConfigs, + SchedulerName: pointer.StringPtr("default-scheduler"), + }, + }, + }, + }, + { + name: "no scheduler name", + config: &v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{}}, + }, + expected: &v1beta3.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ + EnableProfiling: &enable, + EnableContentionProfiling: &enable, + }, + LeaderElection: componentbaseconfig.LeaderElectionConfiguration{ + LeaderElect: pointer.BoolPtr(true), + LeaseDuration: metav1.Duration{Duration: 15 * time.Second}, + RenewDeadline: metav1.Duration{Duration: 10 * time.Second}, + RetryPeriod: metav1.Duration{Duration: 2 * time.Second}, + ResourceLock: "leases", + ResourceNamespace: "kube-system", + ResourceName: "kube-scheduler", + }, + ClientConnection: componentbaseconfig.ClientConnectionConfiguration{ + QPS: 50, + Burst: 100, + ContentType: "application/vnd.kubernetes.protobuf", + }, + PercentageOfNodesToScore: pointer.Int32Ptr(0), + PodInitialBackoffSeconds: pointer.Int64Ptr(1), + PodMaxBackoffSeconds: pointer.Int64Ptr(10), + Profiles: []v1beta3.KubeSchedulerProfile{ + { + SchedulerName: pointer.StringPtr("default-scheduler"), + Plugins: getDefaultPlugins(), + PluginConfig: pluginConfigs}, + }, + }, + }, + { + name: "two profiles", + config: &v1beta3.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + Profiles: []v1beta3.KubeSchedulerProfile{ + { + PluginConfig: []v1beta3.PluginConfig{ + {Name: "FooPlugin"}, + }, + }, + { + SchedulerName: pointer.StringPtr("custom-scheduler"), + Plugins: &v1beta3.Plugins{ + Bind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "BarPlugin"}, + }, + Disabled: []v1beta3.Plugin{ + {Name: names.DefaultBinder}, + }, + }, + }, + }, + }, + }, + expected: &v1beta3.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ + EnableProfiling: &enable, + EnableContentionProfiling: &enable, + }, + LeaderElection: componentbaseconfig.LeaderElectionConfiguration{ + LeaderElect: pointer.BoolPtr(true), + LeaseDuration: metav1.Duration{Duration: 15 * time.Second}, + RenewDeadline: metav1.Duration{Duration: 10 * time.Second}, + RetryPeriod: metav1.Duration{Duration: 2 * time.Second}, + ResourceLock: "leases", + ResourceNamespace: "kube-system", + ResourceName: "kube-scheduler", + }, + ClientConnection: componentbaseconfig.ClientConnectionConfiguration{ + QPS: 50, + Burst: 100, + ContentType: "application/vnd.kubernetes.protobuf", + }, + PercentageOfNodesToScore: pointer.Int32Ptr(0), + PodInitialBackoffSeconds: pointer.Int64Ptr(1), + PodMaxBackoffSeconds: pointer.Int64Ptr(10), + Profiles: []v1beta3.KubeSchedulerProfile{ + { + Plugins: getDefaultPlugins(), + PluginConfig: []v1beta3.PluginConfig{ + {Name: "FooPlugin"}, + { + Name: "DefaultPreemption", + Args: runtime.RawExtension{ + Object: &v1beta3.DefaultPreemptionArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "DefaultPreemptionArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + MinCandidateNodesPercentage: pointer.Int32Ptr(10), + MinCandidateNodesAbsolute: pointer.Int32Ptr(100), + }}, + }, + { + Name: "InterPodAffinity", + Args: runtime.RawExtension{ + Object: &v1beta3.InterPodAffinityArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "InterPodAffinityArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + HardPodAffinityWeight: pointer.Int32Ptr(1), + }}, + }, + { + Name: "NodeAffinity", + Args: runtime.RawExtension{Object: &v1beta3.NodeAffinityArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "NodeAffinityArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + }}, + }, + { + Name: "NodeResourcesBalancedAllocation", + Args: runtime.RawExtension{Object: &v1beta3.NodeResourcesBalancedAllocationArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "NodeResourcesBalancedAllocationArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + Resources: []v1beta3.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }}, + }, + { + Name: "NodeResourcesFit", + Args: runtime.RawExtension{Object: &v1beta3.NodeResourcesFitArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "NodeResourcesFitArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + ScoringStrategy: &v1beta3.ScoringStrategy{ + Type: v1beta3.LeastAllocated, + Resources: []v1beta3.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }, + }}, + }, + { + Name: "PodTopologySpread", + Args: runtime.RawExtension{Object: &v1beta3.PodTopologySpreadArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "PodTopologySpreadArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + DefaultingType: v1beta3.SystemDefaulting, + }}, + }, + { + Name: "VolumeBinding", + Args: runtime.RawExtension{Object: &v1beta3.VolumeBindingArgs{ + TypeMeta: metav1.TypeMeta{ + Kind: "VolumeBindingArgs", + APIVersion: "kubescheduler.config.k8s.io/v1beta3", + }, + BindTimeoutSeconds: pointer.Int64Ptr(600), + }}, + }, + }, + }, + { + SchedulerName: pointer.StringPtr("custom-scheduler"), + Plugins: &v1beta3.Plugins{ + QueueSort: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.PrioritySort}, + }, + }, + PreFilter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.NodeResourcesFit}, + {Name: names.NodePorts}, + {Name: names.VolumeRestrictions}, + {Name: names.PodTopologySpread}, + {Name: names.InterPodAffinity}, + {Name: names.VolumeBinding}, + {Name: names.NodeAffinity}, + }, + }, + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.NodeUnschedulable}, + {Name: names.NodeName}, + {Name: names.TaintToleration}, + {Name: names.NodeAffinity}, + {Name: names.NodePorts}, + {Name: names.NodeResourcesFit}, + {Name: names.VolumeRestrictions}, + {Name: names.EBSLimits}, + {Name: names.GCEPDLimits}, + {Name: names.NodeVolumeLimits}, + {Name: names.AzureDiskLimits}, + {Name: names.VolumeBinding}, + {Name: names.VolumeZone}, + {Name: names.PodTopologySpread}, + {Name: names.InterPodAffinity}, + }, + }, + PostFilter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.DefaultPreemption}, + }, + }, + PreScore: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.InterPodAffinity}, + {Name: names.PodTopologySpread}, + {Name: names.TaintToleration}, + {Name: names.NodeAffinity}, + }, + }, + Score: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.NodeResourcesBalancedAllocation, Weight: pointer.Int32Ptr(1)}, + {Name: names.ImageLocality, Weight: pointer.Int32Ptr(1)}, + {Name: names.NodeResourcesFit, Weight: pointer.Int32Ptr(1)}, + {Name: names.InterPodAffinity, Weight: pointer.Int32Ptr(2)}, + {Name: names.NodeAffinity, Weight: pointer.Int32Ptr(2)}, + {Name: names.PodTopologySpread, Weight: pointer.Int32Ptr(2)}, + {Name: names.TaintToleration, Weight: pointer.Int32Ptr(3)}, + }, + }, + Reserve: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.VolumeBinding}, + }, + }, + PreBind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: names.VolumeBinding}, + }, + }, + Bind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ + {Name: "BarPlugin"}, + }, + }, + }, + PluginConfig: pluginConfigs, + }, + }, + }, + }, + { + name: "Prallelism with no port", + config: &v1beta3.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + }, + expected: &v1beta3.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ + EnableProfiling: &enable, + EnableContentionProfiling: &enable, + }, + LeaderElection: componentbaseconfig.LeaderElectionConfiguration{ + LeaderElect: pointer.BoolPtr(true), + LeaseDuration: metav1.Duration{Duration: 15 * time.Second}, + RenewDeadline: metav1.Duration{Duration: 10 * time.Second}, + RetryPeriod: metav1.Duration{Duration: 2 * time.Second}, + ResourceLock: "leases", + ResourceNamespace: "kube-system", + ResourceName: "kube-scheduler", + }, + ClientConnection: componentbaseconfig.ClientConnectionConfiguration{ + QPS: 50, + Burst: 100, + ContentType: "application/vnd.kubernetes.protobuf", + }, + PercentageOfNodesToScore: pointer.Int32Ptr(0), + PodInitialBackoffSeconds: pointer.Int64Ptr(1), + PodMaxBackoffSeconds: pointer.Int64Ptr(10), + Profiles: []v1beta3.KubeSchedulerProfile{ + { + Plugins: getDefaultPlugins(), + PluginConfig: pluginConfigs, + SchedulerName: pointer.StringPtr("default-scheduler"), + }, + }, + }, + }, + { + name: "set non default parallelism", + config: &v1beta3.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(8), + }, + expected: &v1beta3.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(8), + DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ + EnableProfiling: &enable, + EnableContentionProfiling: &enable, + }, + LeaderElection: componentbaseconfig.LeaderElectionConfiguration{ + LeaderElect: pointer.BoolPtr(true), + LeaseDuration: metav1.Duration{Duration: 15 * time.Second}, + RenewDeadline: metav1.Duration{Duration: 10 * time.Second}, + RetryPeriod: metav1.Duration{Duration: 2 * time.Second}, + ResourceLock: "leases", + ResourceNamespace: "kube-system", + ResourceName: "kube-scheduler", + }, + ClientConnection: componentbaseconfig.ClientConnectionConfiguration{ + QPS: 50, + Burst: 100, + ContentType: "application/vnd.kubernetes.protobuf", + }, + PercentageOfNodesToScore: pointer.Int32Ptr(0), + PodInitialBackoffSeconds: pointer.Int64Ptr(1), + PodMaxBackoffSeconds: pointer.Int64Ptr(10), + Profiles: []v1beta3.KubeSchedulerProfile{ + { + Plugins: getDefaultPlugins(), + PluginConfig: pluginConfigs, + SchedulerName: pointer.StringPtr("default-scheduler"), + }, + }, + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + SetDefaults_KubeSchedulerConfiguration(tc.config) + if diff := cmp.Diff(tc.expected, tc.config); diff != "" { + t.Errorf("Got unexpected defaults (-want, +got):\n%s", diff) + } + }) + } +} + +func TestPluginArgsDefaults(t *testing.T) { + tests := []struct { + name string + features map[featuregate.Feature]bool + in runtime.Object + want runtime.Object + }{ + { + name: "DefaultPreemptionArgs empty", + in: &v1beta3.DefaultPreemptionArgs{}, + want: &v1beta3.DefaultPreemptionArgs{ + MinCandidateNodesPercentage: pointer.Int32Ptr(10), + MinCandidateNodesAbsolute: pointer.Int32Ptr(100), + }, + }, + { + name: "DefaultPreemptionArgs with value", + in: &v1beta3.DefaultPreemptionArgs{ + MinCandidateNodesPercentage: pointer.Int32Ptr(50), + }, + want: &v1beta3.DefaultPreemptionArgs{ + MinCandidateNodesPercentage: pointer.Int32Ptr(50), + MinCandidateNodesAbsolute: pointer.Int32Ptr(100), + }, + }, + { + name: "InterPodAffinityArgs empty", + in: &v1beta3.InterPodAffinityArgs{}, + want: &v1beta3.InterPodAffinityArgs{ + HardPodAffinityWeight: pointer.Int32Ptr(1), + }, + }, + { + name: "InterPodAffinityArgs explicit 0", + in: &v1beta3.InterPodAffinityArgs{ + HardPodAffinityWeight: pointer.Int32Ptr(0), + }, + want: &v1beta3.InterPodAffinityArgs{ + HardPodAffinityWeight: pointer.Int32Ptr(0), + }, + }, + { + name: "InterPodAffinityArgs with value", + in: &v1beta3.InterPodAffinityArgs{ + HardPodAffinityWeight: pointer.Int32Ptr(5), + }, + want: &v1beta3.InterPodAffinityArgs{ + HardPodAffinityWeight: pointer.Int32Ptr(5), + }, + }, + { + name: "NodeResourcesBalancedAllocationArgs resources empty", + in: &v1beta3.NodeResourcesBalancedAllocationArgs{}, + want: &v1beta3.NodeResourcesBalancedAllocationArgs{ + Resources: []v1beta3.ResourceSpec{ + {Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}, + }, + }, + }, + { + name: "NodeResourcesBalancedAllocationArgs with scalar resource", + in: &v1beta3.NodeResourcesBalancedAllocationArgs{ + Resources: []v1beta3.ResourceSpec{ + {Name: "scalar.io/scalar1", Weight: 1}, + }, + }, + want: &v1beta3.NodeResourcesBalancedAllocationArgs{ + Resources: []v1beta3.ResourceSpec{ + {Name: "scalar.io/scalar1", Weight: 1}, + }, + }, + }, + { + name: "NodeResourcesBalancedAllocationArgs with mixed resources", + in: &v1beta3.NodeResourcesBalancedAllocationArgs{ + Resources: []v1beta3.ResourceSpec{ + {Name: string(v1.ResourceCPU), Weight: 1}, + {Name: "scalar.io/scalar1", Weight: 1}, + }, + }, + want: &v1beta3.NodeResourcesBalancedAllocationArgs{ + Resources: []v1beta3.ResourceSpec{ + {Name: string(v1.ResourceCPU), Weight: 1}, + {Name: "scalar.io/scalar1", Weight: 1}, + }, + }, + }, + { + name: "NodeResourcesBalancedAllocationArgs have resource no weight", + in: &v1beta3.NodeResourcesBalancedAllocationArgs{ + Resources: []v1beta3.ResourceSpec{ + {Name: string(v1.ResourceCPU)}, + {Name: "scalar.io/scalar0"}, + {Name: "scalar.io/scalar1", Weight: 1}, + }, + }, + want: &v1beta3.NodeResourcesBalancedAllocationArgs{ + Resources: []v1beta3.ResourceSpec{ + {Name: string(v1.ResourceCPU), Weight: 1}, + {Name: "scalar.io/scalar0", Weight: 1}, + {Name: "scalar.io/scalar1", Weight: 1}, + }, + }, + }, + { + name: "PodTopologySpreadArgs resources empty", + in: &v1beta3.PodTopologySpreadArgs{}, + want: &v1beta3.PodTopologySpreadArgs{ + DefaultingType: v1beta3.SystemDefaulting, + }, + }, + { + name: "PodTopologySpreadArgs resources with value", + in: &v1beta3.PodTopologySpreadArgs{ + DefaultConstraints: []v1.TopologySpreadConstraint{ + { + TopologyKey: "planet", + WhenUnsatisfiable: v1.DoNotSchedule, + MaxSkew: 2, + }, + }, + }, + want: &v1beta3.PodTopologySpreadArgs{ + DefaultConstraints: []v1.TopologySpreadConstraint{ + { + TopologyKey: "planet", + WhenUnsatisfiable: v1.DoNotSchedule, + MaxSkew: 2, + }, + }, + DefaultingType: v1beta3.SystemDefaulting, + }, + }, + { + name: "PodTopologySpreadArgs empty, DefaultPodTopologySpread feature disabled", + features: map[featuregate.Feature]bool{ + features.DefaultPodTopologySpread: false, + }, + in: &v1beta3.PodTopologySpreadArgs{}, + want: &v1beta3.PodTopologySpreadArgs{ + DefaultingType: v1beta3.ListDefaulting, + }, + }, + { + name: "NodeResourcesFitArgs not set", + in: &v1beta3.NodeResourcesFitArgs{}, + want: &v1beta3.NodeResourcesFitArgs{ + ScoringStrategy: &v1beta3.ScoringStrategy{ + Type: v1beta3.LeastAllocated, + Resources: defaultResourceSpec, + }, + }, + }, + { + name: "NodeResourcesFitArgs Resources empty", + in: &v1beta3.NodeResourcesFitArgs{ + ScoringStrategy: &v1beta3.ScoringStrategy{ + Type: v1beta3.MostAllocated, + }, + }, + want: &v1beta3.NodeResourcesFitArgs{ + ScoringStrategy: &v1beta3.ScoringStrategy{ + Type: v1beta3.MostAllocated, + Resources: defaultResourceSpec, + }, + }, + }, + { + name: "VolumeBindingArgs empty, VolumeCapacityPriority disabled", + features: map[featuregate.Feature]bool{ + features.VolumeCapacityPriority: false, + }, + in: &v1beta3.VolumeBindingArgs{}, + want: &v1beta3.VolumeBindingArgs{ + BindTimeoutSeconds: pointer.Int64Ptr(600), + }, + }, + { + name: "VolumeBindingArgs empty, VolumeCapacityPriority enabled", + features: map[featuregate.Feature]bool{ + features.VolumeCapacityPriority: true, + }, + in: &v1beta3.VolumeBindingArgs{}, + want: &v1beta3.VolumeBindingArgs{ + BindTimeoutSeconds: pointer.Int64Ptr(600), + Shape: []v1beta3.UtilizationShapePoint{ + {Utilization: 0, Score: 0}, + {Utilization: 100, Score: 10}, + }, + }, + }, + } + for _, tc := range tests { + scheme := runtime.NewScheme() + utilruntime.Must(AddToScheme(scheme)) + t.Run(tc.name, func(t *testing.T) { + for k, v := range tc.features { + defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, k, v)() + } + scheme.Default(tc.in) + if diff := cmp.Diff(tc.in, tc.want); diff != "" { + t.Errorf("Got unexpected defaults (-want, +got):\n%s", diff) + } + }) + } +} diff --git a/pkg/scheduler/apis/config/v1beta3/doc.go b/pkg/scheduler/apis/config/v1beta3/doc.go new file mode 100644 index 0000000000000..e9976588f1341 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta3/doc.go @@ -0,0 +1,24 @@ +/* +Copyright 2021 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. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:conversion-gen=k8s.io/kubernetes/pkg/scheduler/apis/config +// +k8s:conversion-gen-external-types=k8s.io/kube-scheduler/config/v1beta3 +// +k8s:defaulter-gen=TypeMeta +// +k8s:defaulter-gen-input=k8s.io/kube-scheduler/config/v1beta3 +// +groupName=kubescheduler.config.k8s.io + +package v1beta3 // import "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta3" diff --git a/pkg/scheduler/apis/config/v1beta3/register.go b/pkg/scheduler/apis/config/v1beta3/register.go new file mode 100644 index 0000000000000..2af0952e6f70c --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta3/register.go @@ -0,0 +1,42 @@ +/* +Copyright 2021 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. +*/ + +package v1beta3 + +import ( + "k8s.io/kube-scheduler/config/v1beta3" +) + +// GroupName is the group name used in this package +const GroupName = v1beta3.GroupName + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = v1beta3.SchemeGroupVersion + +var ( + // localSchemeBuilder extends the SchemeBuilder instance with the external types. In this package, + // defaulting and conversion init funcs are registered as well. + localSchemeBuilder = &v1beta3.SchemeBuilder + // AddToScheme is a global function that registers this API group & version to a scheme + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addDefaultingFuncs) +} diff --git a/pkg/scheduler/apis/config/v1beta3/zz_generated.conversion.go b/pkg/scheduler/apis/config/v1beta3/zz_generated.conversion.go new file mode 100644 index 0000000000000..2a2fccd12b7d6 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta3/zz_generated.conversion.go @@ -0,0 +1,859 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +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 conversion-gen. DO NOT EDIT. + +package v1beta3 + +import ( + unsafe "unsafe" + + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + v1alpha1 "k8s.io/component-base/config/v1alpha1" + configv1 "k8s.io/kube-scheduler/config/v1" + v1beta3 "k8s.io/kube-scheduler/config/v1beta3" + config "k8s.io/kubernetes/pkg/scheduler/apis/config" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*v1beta3.DefaultPreemptionArgs)(nil), (*config.DefaultPreemptionArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_DefaultPreemptionArgs_To_config_DefaultPreemptionArgs(a.(*v1beta3.DefaultPreemptionArgs), b.(*config.DefaultPreemptionArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.DefaultPreemptionArgs)(nil), (*v1beta3.DefaultPreemptionArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_DefaultPreemptionArgs_To_v1beta3_DefaultPreemptionArgs(a.(*config.DefaultPreemptionArgs), b.(*v1beta3.DefaultPreemptionArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.Extender)(nil), (*config.Extender)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_Extender_To_config_Extender(a.(*v1beta3.Extender), b.(*config.Extender), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.Extender)(nil), (*v1beta3.Extender)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_Extender_To_v1beta3_Extender(a.(*config.Extender), b.(*v1beta3.Extender), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.InterPodAffinityArgs)(nil), (*config.InterPodAffinityArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_InterPodAffinityArgs_To_config_InterPodAffinityArgs(a.(*v1beta3.InterPodAffinityArgs), b.(*config.InterPodAffinityArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.InterPodAffinityArgs)(nil), (*v1beta3.InterPodAffinityArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_InterPodAffinityArgs_To_v1beta3_InterPodAffinityArgs(a.(*config.InterPodAffinityArgs), b.(*v1beta3.InterPodAffinityArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.KubeSchedulerProfile)(nil), (*config.KubeSchedulerProfile)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_KubeSchedulerProfile_To_config_KubeSchedulerProfile(a.(*v1beta3.KubeSchedulerProfile), b.(*config.KubeSchedulerProfile), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.KubeSchedulerProfile)(nil), (*v1beta3.KubeSchedulerProfile)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_KubeSchedulerProfile_To_v1beta3_KubeSchedulerProfile(a.(*config.KubeSchedulerProfile), b.(*v1beta3.KubeSchedulerProfile), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.NodeAffinityArgs)(nil), (*config.NodeAffinityArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_NodeAffinityArgs_To_config_NodeAffinityArgs(a.(*v1beta3.NodeAffinityArgs), b.(*config.NodeAffinityArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.NodeAffinityArgs)(nil), (*v1beta3.NodeAffinityArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_NodeAffinityArgs_To_v1beta3_NodeAffinityArgs(a.(*config.NodeAffinityArgs), b.(*v1beta3.NodeAffinityArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.NodeResourcesBalancedAllocationArgs)(nil), (*config.NodeResourcesBalancedAllocationArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_NodeResourcesBalancedAllocationArgs_To_config_NodeResourcesBalancedAllocationArgs(a.(*v1beta3.NodeResourcesBalancedAllocationArgs), b.(*config.NodeResourcesBalancedAllocationArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.NodeResourcesBalancedAllocationArgs)(nil), (*v1beta3.NodeResourcesBalancedAllocationArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_NodeResourcesBalancedAllocationArgs_To_v1beta3_NodeResourcesBalancedAllocationArgs(a.(*config.NodeResourcesBalancedAllocationArgs), b.(*v1beta3.NodeResourcesBalancedAllocationArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.NodeResourcesFitArgs)(nil), (*config.NodeResourcesFitArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_NodeResourcesFitArgs_To_config_NodeResourcesFitArgs(a.(*v1beta3.NodeResourcesFitArgs), b.(*config.NodeResourcesFitArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.NodeResourcesFitArgs)(nil), (*v1beta3.NodeResourcesFitArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_NodeResourcesFitArgs_To_v1beta3_NodeResourcesFitArgs(a.(*config.NodeResourcesFitArgs), b.(*v1beta3.NodeResourcesFitArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.Plugin)(nil), (*config.Plugin)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_Plugin_To_config_Plugin(a.(*v1beta3.Plugin), b.(*config.Plugin), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.Plugin)(nil), (*v1beta3.Plugin)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_Plugin_To_v1beta3_Plugin(a.(*config.Plugin), b.(*v1beta3.Plugin), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.PluginConfig)(nil), (*config.PluginConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_PluginConfig_To_config_PluginConfig(a.(*v1beta3.PluginConfig), b.(*config.PluginConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.PluginConfig)(nil), (*v1beta3.PluginConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_PluginConfig_To_v1beta3_PluginConfig(a.(*config.PluginConfig), b.(*v1beta3.PluginConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.PluginSet)(nil), (*config.PluginSet)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_PluginSet_To_config_PluginSet(a.(*v1beta3.PluginSet), b.(*config.PluginSet), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.PluginSet)(nil), (*v1beta3.PluginSet)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_PluginSet_To_v1beta3_PluginSet(a.(*config.PluginSet), b.(*v1beta3.PluginSet), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.Plugins)(nil), (*config.Plugins)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_Plugins_To_config_Plugins(a.(*v1beta3.Plugins), b.(*config.Plugins), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.Plugins)(nil), (*v1beta3.Plugins)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_Plugins_To_v1beta3_Plugins(a.(*config.Plugins), b.(*v1beta3.Plugins), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.PodTopologySpreadArgs)(nil), (*config.PodTopologySpreadArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs(a.(*v1beta3.PodTopologySpreadArgs), b.(*config.PodTopologySpreadArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.PodTopologySpreadArgs)(nil), (*v1beta3.PodTopologySpreadArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_PodTopologySpreadArgs_To_v1beta3_PodTopologySpreadArgs(a.(*config.PodTopologySpreadArgs), b.(*v1beta3.PodTopologySpreadArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.RequestedToCapacityRatioParam)(nil), (*config.RequestedToCapacityRatioParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_RequestedToCapacityRatioParam_To_config_RequestedToCapacityRatioParam(a.(*v1beta3.RequestedToCapacityRatioParam), b.(*config.RequestedToCapacityRatioParam), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.RequestedToCapacityRatioParam)(nil), (*v1beta3.RequestedToCapacityRatioParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_RequestedToCapacityRatioParam_To_v1beta3_RequestedToCapacityRatioParam(a.(*config.RequestedToCapacityRatioParam), b.(*v1beta3.RequestedToCapacityRatioParam), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.ResourceSpec)(nil), (*config.ResourceSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_ResourceSpec_To_config_ResourceSpec(a.(*v1beta3.ResourceSpec), b.(*config.ResourceSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.ResourceSpec)(nil), (*v1beta3.ResourceSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_ResourceSpec_To_v1beta3_ResourceSpec(a.(*config.ResourceSpec), b.(*v1beta3.ResourceSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.ScoringStrategy)(nil), (*config.ScoringStrategy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_ScoringStrategy_To_config_ScoringStrategy(a.(*v1beta3.ScoringStrategy), b.(*config.ScoringStrategy), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.ScoringStrategy)(nil), (*v1beta3.ScoringStrategy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_ScoringStrategy_To_v1beta3_ScoringStrategy(a.(*config.ScoringStrategy), b.(*v1beta3.ScoringStrategy), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.UtilizationShapePoint)(nil), (*config.UtilizationShapePoint)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_UtilizationShapePoint_To_config_UtilizationShapePoint(a.(*v1beta3.UtilizationShapePoint), b.(*config.UtilizationShapePoint), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.UtilizationShapePoint)(nil), (*v1beta3.UtilizationShapePoint)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_UtilizationShapePoint_To_v1beta3_UtilizationShapePoint(a.(*config.UtilizationShapePoint), b.(*v1beta3.UtilizationShapePoint), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta3.VolumeBindingArgs)(nil), (*config.VolumeBindingArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_VolumeBindingArgs_To_config_VolumeBindingArgs(a.(*v1beta3.VolumeBindingArgs), b.(*config.VolumeBindingArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.VolumeBindingArgs)(nil), (*v1beta3.VolumeBindingArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_VolumeBindingArgs_To_v1beta3_VolumeBindingArgs(a.(*config.VolumeBindingArgs), b.(*v1beta3.VolumeBindingArgs), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*config.KubeSchedulerConfiguration)(nil), (*v1beta3.KubeSchedulerConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_KubeSchedulerConfiguration_To_v1beta3_KubeSchedulerConfiguration(a.(*config.KubeSchedulerConfiguration), b.(*v1beta3.KubeSchedulerConfiguration), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta3.KubeSchedulerConfiguration)(nil), (*config.KubeSchedulerConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(a.(*v1beta3.KubeSchedulerConfiguration), b.(*config.KubeSchedulerConfiguration), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta3_DefaultPreemptionArgs_To_config_DefaultPreemptionArgs(in *v1beta3.DefaultPreemptionArgs, out *config.DefaultPreemptionArgs, s conversion.Scope) error { + if err := v1.Convert_Pointer_int32_To_int32(&in.MinCandidateNodesPercentage, &out.MinCandidateNodesPercentage, s); err != nil { + return err + } + if err := v1.Convert_Pointer_int32_To_int32(&in.MinCandidateNodesAbsolute, &out.MinCandidateNodesAbsolute, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta3_DefaultPreemptionArgs_To_config_DefaultPreemptionArgs is an autogenerated conversion function. +func Convert_v1beta3_DefaultPreemptionArgs_To_config_DefaultPreemptionArgs(in *v1beta3.DefaultPreemptionArgs, out *config.DefaultPreemptionArgs, s conversion.Scope) error { + return autoConvert_v1beta3_DefaultPreemptionArgs_To_config_DefaultPreemptionArgs(in, out, s) +} + +func autoConvert_config_DefaultPreemptionArgs_To_v1beta3_DefaultPreemptionArgs(in *config.DefaultPreemptionArgs, out *v1beta3.DefaultPreemptionArgs, s conversion.Scope) error { + if err := v1.Convert_int32_To_Pointer_int32(&in.MinCandidateNodesPercentage, &out.MinCandidateNodesPercentage, s); err != nil { + return err + } + if err := v1.Convert_int32_To_Pointer_int32(&in.MinCandidateNodesAbsolute, &out.MinCandidateNodesAbsolute, s); err != nil { + return err + } + return nil +} + +// Convert_config_DefaultPreemptionArgs_To_v1beta3_DefaultPreemptionArgs is an autogenerated conversion function. +func Convert_config_DefaultPreemptionArgs_To_v1beta3_DefaultPreemptionArgs(in *config.DefaultPreemptionArgs, out *v1beta3.DefaultPreemptionArgs, s conversion.Scope) error { + return autoConvert_config_DefaultPreemptionArgs_To_v1beta3_DefaultPreemptionArgs(in, out, s) +} + +func autoConvert_v1beta3_Extender_To_config_Extender(in *v1beta3.Extender, out *config.Extender, s conversion.Scope) error { + out.URLPrefix = in.URLPrefix + out.FilterVerb = in.FilterVerb + out.PreemptVerb = in.PreemptVerb + out.PrioritizeVerb = in.PrioritizeVerb + out.Weight = in.Weight + out.BindVerb = in.BindVerb + out.EnableHTTPS = in.EnableHTTPS + out.TLSConfig = (*config.ExtenderTLSConfig)(unsafe.Pointer(in.TLSConfig)) + out.HTTPTimeout = in.HTTPTimeout + out.NodeCacheCapable = in.NodeCacheCapable + out.ManagedResources = *(*[]config.ExtenderManagedResource)(unsafe.Pointer(&in.ManagedResources)) + out.Ignorable = in.Ignorable + return nil +} + +// Convert_v1beta3_Extender_To_config_Extender is an autogenerated conversion function. +func Convert_v1beta3_Extender_To_config_Extender(in *v1beta3.Extender, out *config.Extender, s conversion.Scope) error { + return autoConvert_v1beta3_Extender_To_config_Extender(in, out, s) +} + +func autoConvert_config_Extender_To_v1beta3_Extender(in *config.Extender, out *v1beta3.Extender, s conversion.Scope) error { + out.URLPrefix = in.URLPrefix + out.FilterVerb = in.FilterVerb + out.PreemptVerb = in.PreemptVerb + out.PrioritizeVerb = in.PrioritizeVerb + out.Weight = in.Weight + out.BindVerb = in.BindVerb + out.EnableHTTPS = in.EnableHTTPS + out.TLSConfig = (*configv1.ExtenderTLSConfig)(unsafe.Pointer(in.TLSConfig)) + out.HTTPTimeout = in.HTTPTimeout + out.NodeCacheCapable = in.NodeCacheCapable + out.ManagedResources = *(*[]configv1.ExtenderManagedResource)(unsafe.Pointer(&in.ManagedResources)) + out.Ignorable = in.Ignorable + return nil +} + +// Convert_config_Extender_To_v1beta3_Extender is an autogenerated conversion function. +func Convert_config_Extender_To_v1beta3_Extender(in *config.Extender, out *v1beta3.Extender, s conversion.Scope) error { + return autoConvert_config_Extender_To_v1beta3_Extender(in, out, s) +} + +func autoConvert_v1beta3_InterPodAffinityArgs_To_config_InterPodAffinityArgs(in *v1beta3.InterPodAffinityArgs, out *config.InterPodAffinityArgs, s conversion.Scope) error { + if err := v1.Convert_Pointer_int32_To_int32(&in.HardPodAffinityWeight, &out.HardPodAffinityWeight, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta3_InterPodAffinityArgs_To_config_InterPodAffinityArgs is an autogenerated conversion function. +func Convert_v1beta3_InterPodAffinityArgs_To_config_InterPodAffinityArgs(in *v1beta3.InterPodAffinityArgs, out *config.InterPodAffinityArgs, s conversion.Scope) error { + return autoConvert_v1beta3_InterPodAffinityArgs_To_config_InterPodAffinityArgs(in, out, s) +} + +func autoConvert_config_InterPodAffinityArgs_To_v1beta3_InterPodAffinityArgs(in *config.InterPodAffinityArgs, out *v1beta3.InterPodAffinityArgs, s conversion.Scope) error { + if err := v1.Convert_int32_To_Pointer_int32(&in.HardPodAffinityWeight, &out.HardPodAffinityWeight, s); err != nil { + return err + } + return nil +} + +// Convert_config_InterPodAffinityArgs_To_v1beta3_InterPodAffinityArgs is an autogenerated conversion function. +func Convert_config_InterPodAffinityArgs_To_v1beta3_InterPodAffinityArgs(in *config.InterPodAffinityArgs, out *v1beta3.InterPodAffinityArgs, s conversion.Scope) error { + return autoConvert_config_InterPodAffinityArgs_To_v1beta3_InterPodAffinityArgs(in, out, s) +} + +func autoConvert_v1beta3_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(in *v1beta3.KubeSchedulerConfiguration, out *config.KubeSchedulerConfiguration, s conversion.Scope) error { + if err := v1.Convert_Pointer_int32_To_int32(&in.Parallelism, &out.Parallelism, s); err != nil { + return err + } + if err := v1alpha1.Convert_v1alpha1_LeaderElectionConfiguration_To_config_LeaderElectionConfiguration(&in.LeaderElection, &out.LeaderElection, s); err != nil { + return err + } + if err := v1alpha1.Convert_v1alpha1_ClientConnectionConfiguration_To_config_ClientConnectionConfiguration(&in.ClientConnection, &out.ClientConnection, s); err != nil { + return err + } + if err := v1alpha1.Convert_v1alpha1_DebuggingConfiguration_To_config_DebuggingConfiguration(&in.DebuggingConfiguration, &out.DebuggingConfiguration, s); err != nil { + return err + } + if err := v1.Convert_Pointer_int32_To_int32(&in.PercentageOfNodesToScore, &out.PercentageOfNodesToScore, s); err != nil { + return err + } + if err := v1.Convert_Pointer_int64_To_int64(&in.PodInitialBackoffSeconds, &out.PodInitialBackoffSeconds, s); err != nil { + return err + } + if err := v1.Convert_Pointer_int64_To_int64(&in.PodMaxBackoffSeconds, &out.PodMaxBackoffSeconds, s); err != nil { + return err + } + if in.Profiles != nil { + in, out := &in.Profiles, &out.Profiles + *out = make([]config.KubeSchedulerProfile, len(*in)) + for i := range *in { + if err := Convert_v1beta3_KubeSchedulerProfile_To_config_KubeSchedulerProfile(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Profiles = nil + } + out.Extenders = *(*[]config.Extender)(unsafe.Pointer(&in.Extenders)) + return nil +} + +func autoConvert_config_KubeSchedulerConfiguration_To_v1beta3_KubeSchedulerConfiguration(in *config.KubeSchedulerConfiguration, out *v1beta3.KubeSchedulerConfiguration, s conversion.Scope) error { + if err := v1.Convert_int32_To_Pointer_int32(&in.Parallelism, &out.Parallelism, s); err != nil { + return err + } + if err := v1alpha1.Convert_config_LeaderElectionConfiguration_To_v1alpha1_LeaderElectionConfiguration(&in.LeaderElection, &out.LeaderElection, s); err != nil { + return err + } + if err := v1alpha1.Convert_config_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration(&in.ClientConnection, &out.ClientConnection, s); err != nil { + return err + } + // WARNING: in.HealthzBindAddress requires manual conversion: does not exist in peer-type + // WARNING: in.MetricsBindAddress requires manual conversion: does not exist in peer-type + if err := v1alpha1.Convert_config_DebuggingConfiguration_To_v1alpha1_DebuggingConfiguration(&in.DebuggingConfiguration, &out.DebuggingConfiguration, s); err != nil { + return err + } + if err := v1.Convert_int32_To_Pointer_int32(&in.PercentageOfNodesToScore, &out.PercentageOfNodesToScore, s); err != nil { + return err + } + if err := v1.Convert_int64_To_Pointer_int64(&in.PodInitialBackoffSeconds, &out.PodInitialBackoffSeconds, s); err != nil { + return err + } + if err := v1.Convert_int64_To_Pointer_int64(&in.PodMaxBackoffSeconds, &out.PodMaxBackoffSeconds, s); err != nil { + return err + } + if in.Profiles != nil { + in, out := &in.Profiles, &out.Profiles + *out = make([]v1beta3.KubeSchedulerProfile, len(*in)) + for i := range *in { + if err := Convert_config_KubeSchedulerProfile_To_v1beta3_KubeSchedulerProfile(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Profiles = nil + } + out.Extenders = *(*[]v1beta3.Extender)(unsafe.Pointer(&in.Extenders)) + return nil +} + +func autoConvert_v1beta3_KubeSchedulerProfile_To_config_KubeSchedulerProfile(in *v1beta3.KubeSchedulerProfile, out *config.KubeSchedulerProfile, s conversion.Scope) error { + if err := v1.Convert_Pointer_string_To_string(&in.SchedulerName, &out.SchedulerName, s); err != nil { + return err + } + if in.Plugins != nil { + in, out := &in.Plugins, &out.Plugins + *out = new(config.Plugins) + if err := Convert_v1beta3_Plugins_To_config_Plugins(*in, *out, s); err != nil { + return err + } + } else { + out.Plugins = nil + } + if in.PluginConfig != nil { + in, out := &in.PluginConfig, &out.PluginConfig + *out = make([]config.PluginConfig, len(*in)) + for i := range *in { + if err := Convert_v1beta3_PluginConfig_To_config_PluginConfig(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.PluginConfig = nil + } + return nil +} + +// Convert_v1beta3_KubeSchedulerProfile_To_config_KubeSchedulerProfile is an autogenerated conversion function. +func Convert_v1beta3_KubeSchedulerProfile_To_config_KubeSchedulerProfile(in *v1beta3.KubeSchedulerProfile, out *config.KubeSchedulerProfile, s conversion.Scope) error { + return autoConvert_v1beta3_KubeSchedulerProfile_To_config_KubeSchedulerProfile(in, out, s) +} + +func autoConvert_config_KubeSchedulerProfile_To_v1beta3_KubeSchedulerProfile(in *config.KubeSchedulerProfile, out *v1beta3.KubeSchedulerProfile, s conversion.Scope) error { + if err := v1.Convert_string_To_Pointer_string(&in.SchedulerName, &out.SchedulerName, s); err != nil { + return err + } + if in.Plugins != nil { + in, out := &in.Plugins, &out.Plugins + *out = new(v1beta3.Plugins) + if err := Convert_config_Plugins_To_v1beta3_Plugins(*in, *out, s); err != nil { + return err + } + } else { + out.Plugins = nil + } + if in.PluginConfig != nil { + in, out := &in.PluginConfig, &out.PluginConfig + *out = make([]v1beta3.PluginConfig, len(*in)) + for i := range *in { + if err := Convert_config_PluginConfig_To_v1beta3_PluginConfig(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.PluginConfig = nil + } + return nil +} + +// Convert_config_KubeSchedulerProfile_To_v1beta3_KubeSchedulerProfile is an autogenerated conversion function. +func Convert_config_KubeSchedulerProfile_To_v1beta3_KubeSchedulerProfile(in *config.KubeSchedulerProfile, out *v1beta3.KubeSchedulerProfile, s conversion.Scope) error { + return autoConvert_config_KubeSchedulerProfile_To_v1beta3_KubeSchedulerProfile(in, out, s) +} + +func autoConvert_v1beta3_NodeAffinityArgs_To_config_NodeAffinityArgs(in *v1beta3.NodeAffinityArgs, out *config.NodeAffinityArgs, s conversion.Scope) error { + out.AddedAffinity = (*corev1.NodeAffinity)(unsafe.Pointer(in.AddedAffinity)) + return nil +} + +// Convert_v1beta3_NodeAffinityArgs_To_config_NodeAffinityArgs is an autogenerated conversion function. +func Convert_v1beta3_NodeAffinityArgs_To_config_NodeAffinityArgs(in *v1beta3.NodeAffinityArgs, out *config.NodeAffinityArgs, s conversion.Scope) error { + return autoConvert_v1beta3_NodeAffinityArgs_To_config_NodeAffinityArgs(in, out, s) +} + +func autoConvert_config_NodeAffinityArgs_To_v1beta3_NodeAffinityArgs(in *config.NodeAffinityArgs, out *v1beta3.NodeAffinityArgs, s conversion.Scope) error { + out.AddedAffinity = (*corev1.NodeAffinity)(unsafe.Pointer(in.AddedAffinity)) + return nil +} + +// Convert_config_NodeAffinityArgs_To_v1beta3_NodeAffinityArgs is an autogenerated conversion function. +func Convert_config_NodeAffinityArgs_To_v1beta3_NodeAffinityArgs(in *config.NodeAffinityArgs, out *v1beta3.NodeAffinityArgs, s conversion.Scope) error { + return autoConvert_config_NodeAffinityArgs_To_v1beta3_NodeAffinityArgs(in, out, s) +} + +func autoConvert_v1beta3_NodeResourcesBalancedAllocationArgs_To_config_NodeResourcesBalancedAllocationArgs(in *v1beta3.NodeResourcesBalancedAllocationArgs, out *config.NodeResourcesBalancedAllocationArgs, s conversion.Scope) error { + out.Resources = *(*[]config.ResourceSpec)(unsafe.Pointer(&in.Resources)) + return nil +} + +// Convert_v1beta3_NodeResourcesBalancedAllocationArgs_To_config_NodeResourcesBalancedAllocationArgs is an autogenerated conversion function. +func Convert_v1beta3_NodeResourcesBalancedAllocationArgs_To_config_NodeResourcesBalancedAllocationArgs(in *v1beta3.NodeResourcesBalancedAllocationArgs, out *config.NodeResourcesBalancedAllocationArgs, s conversion.Scope) error { + return autoConvert_v1beta3_NodeResourcesBalancedAllocationArgs_To_config_NodeResourcesBalancedAllocationArgs(in, out, s) +} + +func autoConvert_config_NodeResourcesBalancedAllocationArgs_To_v1beta3_NodeResourcesBalancedAllocationArgs(in *config.NodeResourcesBalancedAllocationArgs, out *v1beta3.NodeResourcesBalancedAllocationArgs, s conversion.Scope) error { + out.Resources = *(*[]v1beta3.ResourceSpec)(unsafe.Pointer(&in.Resources)) + return nil +} + +// Convert_config_NodeResourcesBalancedAllocationArgs_To_v1beta3_NodeResourcesBalancedAllocationArgs is an autogenerated conversion function. +func Convert_config_NodeResourcesBalancedAllocationArgs_To_v1beta3_NodeResourcesBalancedAllocationArgs(in *config.NodeResourcesBalancedAllocationArgs, out *v1beta3.NodeResourcesBalancedAllocationArgs, s conversion.Scope) error { + return autoConvert_config_NodeResourcesBalancedAllocationArgs_To_v1beta3_NodeResourcesBalancedAllocationArgs(in, out, s) +} + +func autoConvert_v1beta3_NodeResourcesFitArgs_To_config_NodeResourcesFitArgs(in *v1beta3.NodeResourcesFitArgs, out *config.NodeResourcesFitArgs, s conversion.Scope) error { + out.IgnoredResources = *(*[]string)(unsafe.Pointer(&in.IgnoredResources)) + out.IgnoredResourceGroups = *(*[]string)(unsafe.Pointer(&in.IgnoredResourceGroups)) + out.ScoringStrategy = (*config.ScoringStrategy)(unsafe.Pointer(in.ScoringStrategy)) + return nil +} + +// Convert_v1beta3_NodeResourcesFitArgs_To_config_NodeResourcesFitArgs is an autogenerated conversion function. +func Convert_v1beta3_NodeResourcesFitArgs_To_config_NodeResourcesFitArgs(in *v1beta3.NodeResourcesFitArgs, out *config.NodeResourcesFitArgs, s conversion.Scope) error { + return autoConvert_v1beta3_NodeResourcesFitArgs_To_config_NodeResourcesFitArgs(in, out, s) +} + +func autoConvert_config_NodeResourcesFitArgs_To_v1beta3_NodeResourcesFitArgs(in *config.NodeResourcesFitArgs, out *v1beta3.NodeResourcesFitArgs, s conversion.Scope) error { + out.IgnoredResources = *(*[]string)(unsafe.Pointer(&in.IgnoredResources)) + out.IgnoredResourceGroups = *(*[]string)(unsafe.Pointer(&in.IgnoredResourceGroups)) + out.ScoringStrategy = (*v1beta3.ScoringStrategy)(unsafe.Pointer(in.ScoringStrategy)) + return nil +} + +// Convert_config_NodeResourcesFitArgs_To_v1beta3_NodeResourcesFitArgs is an autogenerated conversion function. +func Convert_config_NodeResourcesFitArgs_To_v1beta3_NodeResourcesFitArgs(in *config.NodeResourcesFitArgs, out *v1beta3.NodeResourcesFitArgs, s conversion.Scope) error { + return autoConvert_config_NodeResourcesFitArgs_To_v1beta3_NodeResourcesFitArgs(in, out, s) +} + +func autoConvert_v1beta3_Plugin_To_config_Plugin(in *v1beta3.Plugin, out *config.Plugin, s conversion.Scope) error { + out.Name = in.Name + if err := v1.Convert_Pointer_int32_To_int32(&in.Weight, &out.Weight, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta3_Plugin_To_config_Plugin is an autogenerated conversion function. +func Convert_v1beta3_Plugin_To_config_Plugin(in *v1beta3.Plugin, out *config.Plugin, s conversion.Scope) error { + return autoConvert_v1beta3_Plugin_To_config_Plugin(in, out, s) +} + +func autoConvert_config_Plugin_To_v1beta3_Plugin(in *config.Plugin, out *v1beta3.Plugin, s conversion.Scope) error { + out.Name = in.Name + if err := v1.Convert_int32_To_Pointer_int32(&in.Weight, &out.Weight, s); err != nil { + return err + } + return nil +} + +// Convert_config_Plugin_To_v1beta3_Plugin is an autogenerated conversion function. +func Convert_config_Plugin_To_v1beta3_Plugin(in *config.Plugin, out *v1beta3.Plugin, s conversion.Scope) error { + return autoConvert_config_Plugin_To_v1beta3_Plugin(in, out, s) +} + +func autoConvert_v1beta3_PluginConfig_To_config_PluginConfig(in *v1beta3.PluginConfig, out *config.PluginConfig, s conversion.Scope) error { + out.Name = in.Name + if err := runtime.Convert_runtime_RawExtension_To_runtime_Object(&in.Args, &out.Args, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta3_PluginConfig_To_config_PluginConfig is an autogenerated conversion function. +func Convert_v1beta3_PluginConfig_To_config_PluginConfig(in *v1beta3.PluginConfig, out *config.PluginConfig, s conversion.Scope) error { + return autoConvert_v1beta3_PluginConfig_To_config_PluginConfig(in, out, s) +} + +func autoConvert_config_PluginConfig_To_v1beta3_PluginConfig(in *config.PluginConfig, out *v1beta3.PluginConfig, s conversion.Scope) error { + out.Name = in.Name + if err := runtime.Convert_runtime_Object_To_runtime_RawExtension(&in.Args, &out.Args, s); err != nil { + return err + } + return nil +} + +// Convert_config_PluginConfig_To_v1beta3_PluginConfig is an autogenerated conversion function. +func Convert_config_PluginConfig_To_v1beta3_PluginConfig(in *config.PluginConfig, out *v1beta3.PluginConfig, s conversion.Scope) error { + return autoConvert_config_PluginConfig_To_v1beta3_PluginConfig(in, out, s) +} + +func autoConvert_v1beta3_PluginSet_To_config_PluginSet(in *v1beta3.PluginSet, out *config.PluginSet, s conversion.Scope) error { + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = make([]config.Plugin, len(*in)) + for i := range *in { + if err := Convert_v1beta3_Plugin_To_config_Plugin(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Enabled = nil + } + if in.Disabled != nil { + in, out := &in.Disabled, &out.Disabled + *out = make([]config.Plugin, len(*in)) + for i := range *in { + if err := Convert_v1beta3_Plugin_To_config_Plugin(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Disabled = nil + } + return nil +} + +// Convert_v1beta3_PluginSet_To_config_PluginSet is an autogenerated conversion function. +func Convert_v1beta3_PluginSet_To_config_PluginSet(in *v1beta3.PluginSet, out *config.PluginSet, s conversion.Scope) error { + return autoConvert_v1beta3_PluginSet_To_config_PluginSet(in, out, s) +} + +func autoConvert_config_PluginSet_To_v1beta3_PluginSet(in *config.PluginSet, out *v1beta3.PluginSet, s conversion.Scope) error { + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = make([]v1beta3.Plugin, len(*in)) + for i := range *in { + if err := Convert_config_Plugin_To_v1beta3_Plugin(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Enabled = nil + } + if in.Disabled != nil { + in, out := &in.Disabled, &out.Disabled + *out = make([]v1beta3.Plugin, len(*in)) + for i := range *in { + if err := Convert_config_Plugin_To_v1beta3_Plugin(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Disabled = nil + } + return nil +} + +// Convert_config_PluginSet_To_v1beta3_PluginSet is an autogenerated conversion function. +func Convert_config_PluginSet_To_v1beta3_PluginSet(in *config.PluginSet, out *v1beta3.PluginSet, s conversion.Scope) error { + return autoConvert_config_PluginSet_To_v1beta3_PluginSet(in, out, s) +} + +func autoConvert_v1beta3_Plugins_To_config_Plugins(in *v1beta3.Plugins, out *config.Plugins, s conversion.Scope) error { + if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.QueueSort, &out.QueueSort, s); err != nil { + return err + } + if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.PreFilter, &out.PreFilter, s); err != nil { + return err + } + if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.Filter, &out.Filter, s); err != nil { + return err + } + if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.PostFilter, &out.PostFilter, s); err != nil { + return err + } + if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.PreScore, &out.PreScore, s); err != nil { + return err + } + if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.Score, &out.Score, s); err != nil { + return err + } + if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.Reserve, &out.Reserve, s); err != nil { + return err + } + if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.Permit, &out.Permit, s); err != nil { + return err + } + if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.PreBind, &out.PreBind, s); err != nil { + return err + } + if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.Bind, &out.Bind, s); err != nil { + return err + } + if err := Convert_v1beta3_PluginSet_To_config_PluginSet(&in.PostBind, &out.PostBind, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta3_Plugins_To_config_Plugins is an autogenerated conversion function. +func Convert_v1beta3_Plugins_To_config_Plugins(in *v1beta3.Plugins, out *config.Plugins, s conversion.Scope) error { + return autoConvert_v1beta3_Plugins_To_config_Plugins(in, out, s) +} + +func autoConvert_config_Plugins_To_v1beta3_Plugins(in *config.Plugins, out *v1beta3.Plugins, s conversion.Scope) error { + if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.QueueSort, &out.QueueSort, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.PreFilter, &out.PreFilter, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.Filter, &out.Filter, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.PostFilter, &out.PostFilter, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.PreScore, &out.PreScore, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.Score, &out.Score, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.Reserve, &out.Reserve, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.Permit, &out.Permit, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.PreBind, &out.PreBind, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.Bind, &out.Bind, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta3_PluginSet(&in.PostBind, &out.PostBind, s); err != nil { + return err + } + return nil +} + +// Convert_config_Plugins_To_v1beta3_Plugins is an autogenerated conversion function. +func Convert_config_Plugins_To_v1beta3_Plugins(in *config.Plugins, out *v1beta3.Plugins, s conversion.Scope) error { + return autoConvert_config_Plugins_To_v1beta3_Plugins(in, out, s) +} + +func autoConvert_v1beta3_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs(in *v1beta3.PodTopologySpreadArgs, out *config.PodTopologySpreadArgs, s conversion.Scope) error { + out.DefaultConstraints = *(*[]corev1.TopologySpreadConstraint)(unsafe.Pointer(&in.DefaultConstraints)) + out.DefaultingType = config.PodTopologySpreadConstraintsDefaulting(in.DefaultingType) + return nil +} + +// Convert_v1beta3_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs is an autogenerated conversion function. +func Convert_v1beta3_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs(in *v1beta3.PodTopologySpreadArgs, out *config.PodTopologySpreadArgs, s conversion.Scope) error { + return autoConvert_v1beta3_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs(in, out, s) +} + +func autoConvert_config_PodTopologySpreadArgs_To_v1beta3_PodTopologySpreadArgs(in *config.PodTopologySpreadArgs, out *v1beta3.PodTopologySpreadArgs, s conversion.Scope) error { + out.DefaultConstraints = *(*[]corev1.TopologySpreadConstraint)(unsafe.Pointer(&in.DefaultConstraints)) + out.DefaultingType = v1beta3.PodTopologySpreadConstraintsDefaulting(in.DefaultingType) + return nil +} + +// Convert_config_PodTopologySpreadArgs_To_v1beta3_PodTopologySpreadArgs is an autogenerated conversion function. +func Convert_config_PodTopologySpreadArgs_To_v1beta3_PodTopologySpreadArgs(in *config.PodTopologySpreadArgs, out *v1beta3.PodTopologySpreadArgs, s conversion.Scope) error { + return autoConvert_config_PodTopologySpreadArgs_To_v1beta3_PodTopologySpreadArgs(in, out, s) +} + +func autoConvert_v1beta3_RequestedToCapacityRatioParam_To_config_RequestedToCapacityRatioParam(in *v1beta3.RequestedToCapacityRatioParam, out *config.RequestedToCapacityRatioParam, s conversion.Scope) error { + out.Shape = *(*[]config.UtilizationShapePoint)(unsafe.Pointer(&in.Shape)) + return nil +} + +// Convert_v1beta3_RequestedToCapacityRatioParam_To_config_RequestedToCapacityRatioParam is an autogenerated conversion function. +func Convert_v1beta3_RequestedToCapacityRatioParam_To_config_RequestedToCapacityRatioParam(in *v1beta3.RequestedToCapacityRatioParam, out *config.RequestedToCapacityRatioParam, s conversion.Scope) error { + return autoConvert_v1beta3_RequestedToCapacityRatioParam_To_config_RequestedToCapacityRatioParam(in, out, s) +} + +func autoConvert_config_RequestedToCapacityRatioParam_To_v1beta3_RequestedToCapacityRatioParam(in *config.RequestedToCapacityRatioParam, out *v1beta3.RequestedToCapacityRatioParam, s conversion.Scope) error { + out.Shape = *(*[]v1beta3.UtilizationShapePoint)(unsafe.Pointer(&in.Shape)) + return nil +} + +// Convert_config_RequestedToCapacityRatioParam_To_v1beta3_RequestedToCapacityRatioParam is an autogenerated conversion function. +func Convert_config_RequestedToCapacityRatioParam_To_v1beta3_RequestedToCapacityRatioParam(in *config.RequestedToCapacityRatioParam, out *v1beta3.RequestedToCapacityRatioParam, s conversion.Scope) error { + return autoConvert_config_RequestedToCapacityRatioParam_To_v1beta3_RequestedToCapacityRatioParam(in, out, s) +} + +func autoConvert_v1beta3_ResourceSpec_To_config_ResourceSpec(in *v1beta3.ResourceSpec, out *config.ResourceSpec, s conversion.Scope) error { + out.Name = in.Name + out.Weight = in.Weight + return nil +} + +// Convert_v1beta3_ResourceSpec_To_config_ResourceSpec is an autogenerated conversion function. +func Convert_v1beta3_ResourceSpec_To_config_ResourceSpec(in *v1beta3.ResourceSpec, out *config.ResourceSpec, s conversion.Scope) error { + return autoConvert_v1beta3_ResourceSpec_To_config_ResourceSpec(in, out, s) +} + +func autoConvert_config_ResourceSpec_To_v1beta3_ResourceSpec(in *config.ResourceSpec, out *v1beta3.ResourceSpec, s conversion.Scope) error { + out.Name = in.Name + out.Weight = in.Weight + return nil +} + +// Convert_config_ResourceSpec_To_v1beta3_ResourceSpec is an autogenerated conversion function. +func Convert_config_ResourceSpec_To_v1beta3_ResourceSpec(in *config.ResourceSpec, out *v1beta3.ResourceSpec, s conversion.Scope) error { + return autoConvert_config_ResourceSpec_To_v1beta3_ResourceSpec(in, out, s) +} + +func autoConvert_v1beta3_ScoringStrategy_To_config_ScoringStrategy(in *v1beta3.ScoringStrategy, out *config.ScoringStrategy, s conversion.Scope) error { + out.Type = config.ScoringStrategyType(in.Type) + out.Resources = *(*[]config.ResourceSpec)(unsafe.Pointer(&in.Resources)) + out.RequestedToCapacityRatio = (*config.RequestedToCapacityRatioParam)(unsafe.Pointer(in.RequestedToCapacityRatio)) + return nil +} + +// Convert_v1beta3_ScoringStrategy_To_config_ScoringStrategy is an autogenerated conversion function. +func Convert_v1beta3_ScoringStrategy_To_config_ScoringStrategy(in *v1beta3.ScoringStrategy, out *config.ScoringStrategy, s conversion.Scope) error { + return autoConvert_v1beta3_ScoringStrategy_To_config_ScoringStrategy(in, out, s) +} + +func autoConvert_config_ScoringStrategy_To_v1beta3_ScoringStrategy(in *config.ScoringStrategy, out *v1beta3.ScoringStrategy, s conversion.Scope) error { + out.Type = v1beta3.ScoringStrategyType(in.Type) + out.Resources = *(*[]v1beta3.ResourceSpec)(unsafe.Pointer(&in.Resources)) + out.RequestedToCapacityRatio = (*v1beta3.RequestedToCapacityRatioParam)(unsafe.Pointer(in.RequestedToCapacityRatio)) + return nil +} + +// Convert_config_ScoringStrategy_To_v1beta3_ScoringStrategy is an autogenerated conversion function. +func Convert_config_ScoringStrategy_To_v1beta3_ScoringStrategy(in *config.ScoringStrategy, out *v1beta3.ScoringStrategy, s conversion.Scope) error { + return autoConvert_config_ScoringStrategy_To_v1beta3_ScoringStrategy(in, out, s) +} + +func autoConvert_v1beta3_UtilizationShapePoint_To_config_UtilizationShapePoint(in *v1beta3.UtilizationShapePoint, out *config.UtilizationShapePoint, s conversion.Scope) error { + out.Utilization = in.Utilization + out.Score = in.Score + return nil +} + +// Convert_v1beta3_UtilizationShapePoint_To_config_UtilizationShapePoint is an autogenerated conversion function. +func Convert_v1beta3_UtilizationShapePoint_To_config_UtilizationShapePoint(in *v1beta3.UtilizationShapePoint, out *config.UtilizationShapePoint, s conversion.Scope) error { + return autoConvert_v1beta3_UtilizationShapePoint_To_config_UtilizationShapePoint(in, out, s) +} + +func autoConvert_config_UtilizationShapePoint_To_v1beta3_UtilizationShapePoint(in *config.UtilizationShapePoint, out *v1beta3.UtilizationShapePoint, s conversion.Scope) error { + out.Utilization = in.Utilization + out.Score = in.Score + return nil +} + +// Convert_config_UtilizationShapePoint_To_v1beta3_UtilizationShapePoint is an autogenerated conversion function. +func Convert_config_UtilizationShapePoint_To_v1beta3_UtilizationShapePoint(in *config.UtilizationShapePoint, out *v1beta3.UtilizationShapePoint, s conversion.Scope) error { + return autoConvert_config_UtilizationShapePoint_To_v1beta3_UtilizationShapePoint(in, out, s) +} + +func autoConvert_v1beta3_VolumeBindingArgs_To_config_VolumeBindingArgs(in *v1beta3.VolumeBindingArgs, out *config.VolumeBindingArgs, s conversion.Scope) error { + if err := v1.Convert_Pointer_int64_To_int64(&in.BindTimeoutSeconds, &out.BindTimeoutSeconds, s); err != nil { + return err + } + out.Shape = *(*[]config.UtilizationShapePoint)(unsafe.Pointer(&in.Shape)) + return nil +} + +// Convert_v1beta3_VolumeBindingArgs_To_config_VolumeBindingArgs is an autogenerated conversion function. +func Convert_v1beta3_VolumeBindingArgs_To_config_VolumeBindingArgs(in *v1beta3.VolumeBindingArgs, out *config.VolumeBindingArgs, s conversion.Scope) error { + return autoConvert_v1beta3_VolumeBindingArgs_To_config_VolumeBindingArgs(in, out, s) +} + +func autoConvert_config_VolumeBindingArgs_To_v1beta3_VolumeBindingArgs(in *config.VolumeBindingArgs, out *v1beta3.VolumeBindingArgs, s conversion.Scope) error { + if err := v1.Convert_int64_To_Pointer_int64(&in.BindTimeoutSeconds, &out.BindTimeoutSeconds, s); err != nil { + return err + } + out.Shape = *(*[]v1beta3.UtilizationShapePoint)(unsafe.Pointer(&in.Shape)) + return nil +} + +// Convert_config_VolumeBindingArgs_To_v1beta3_VolumeBindingArgs is an autogenerated conversion function. +func Convert_config_VolumeBindingArgs_To_v1beta3_VolumeBindingArgs(in *config.VolumeBindingArgs, out *v1beta3.VolumeBindingArgs, s conversion.Scope) error { + return autoConvert_config_VolumeBindingArgs_To_v1beta3_VolumeBindingArgs(in, out, s) +} diff --git a/pkg/scheduler/apis/config/v1beta3/zz_generated.deepcopy.go b/pkg/scheduler/apis/config/v1beta3/zz_generated.deepcopy.go new file mode 100644 index 0000000000000..e735e37dbb1fa --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta3/zz_generated.deepcopy.go @@ -0,0 +1,22 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +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 deepcopy-gen. DO NOT EDIT. + +package v1beta3 diff --git a/pkg/scheduler/apis/config/v1beta3/zz_generated.defaults.go b/pkg/scheduler/apis/config/v1beta3/zz_generated.defaults.go new file mode 100644 index 0000000000000..3c28679f62f06 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta3/zz_generated.defaults.go @@ -0,0 +1,73 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +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 defaulter-gen. DO NOT EDIT. + +package v1beta3 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + v1beta3 "k8s.io/kube-scheduler/config/v1beta3" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + scheme.AddTypeDefaultingFunc(&v1beta3.DefaultPreemptionArgs{}, func(obj interface{}) { SetObjectDefaults_DefaultPreemptionArgs(obj.(*v1beta3.DefaultPreemptionArgs)) }) + scheme.AddTypeDefaultingFunc(&v1beta3.InterPodAffinityArgs{}, func(obj interface{}) { SetObjectDefaults_InterPodAffinityArgs(obj.(*v1beta3.InterPodAffinityArgs)) }) + scheme.AddTypeDefaultingFunc(&v1beta3.KubeSchedulerConfiguration{}, func(obj interface{}) { + SetObjectDefaults_KubeSchedulerConfiguration(obj.(*v1beta3.KubeSchedulerConfiguration)) + }) + scheme.AddTypeDefaultingFunc(&v1beta3.NodeResourcesBalancedAllocationArgs{}, func(obj interface{}) { + SetObjectDefaults_NodeResourcesBalancedAllocationArgs(obj.(*v1beta3.NodeResourcesBalancedAllocationArgs)) + }) + scheme.AddTypeDefaultingFunc(&v1beta3.NodeResourcesFitArgs{}, func(obj interface{}) { SetObjectDefaults_NodeResourcesFitArgs(obj.(*v1beta3.NodeResourcesFitArgs)) }) + scheme.AddTypeDefaultingFunc(&v1beta3.PodTopologySpreadArgs{}, func(obj interface{}) { SetObjectDefaults_PodTopologySpreadArgs(obj.(*v1beta3.PodTopologySpreadArgs)) }) + scheme.AddTypeDefaultingFunc(&v1beta3.VolumeBindingArgs{}, func(obj interface{}) { SetObjectDefaults_VolumeBindingArgs(obj.(*v1beta3.VolumeBindingArgs)) }) + return nil +} + +func SetObjectDefaults_DefaultPreemptionArgs(in *v1beta3.DefaultPreemptionArgs) { + SetDefaults_DefaultPreemptionArgs(in) +} + +func SetObjectDefaults_InterPodAffinityArgs(in *v1beta3.InterPodAffinityArgs) { + SetDefaults_InterPodAffinityArgs(in) +} + +func SetObjectDefaults_KubeSchedulerConfiguration(in *v1beta3.KubeSchedulerConfiguration) { + SetDefaults_KubeSchedulerConfiguration(in) +} + +func SetObjectDefaults_NodeResourcesBalancedAllocationArgs(in *v1beta3.NodeResourcesBalancedAllocationArgs) { + SetDefaults_NodeResourcesBalancedAllocationArgs(in) +} + +func SetObjectDefaults_NodeResourcesFitArgs(in *v1beta3.NodeResourcesFitArgs) { + SetDefaults_NodeResourcesFitArgs(in) +} + +func SetObjectDefaults_PodTopologySpreadArgs(in *v1beta3.PodTopologySpreadArgs) { + SetDefaults_PodTopologySpreadArgs(in) +} + +func SetObjectDefaults_VolumeBindingArgs(in *v1beta3.VolumeBindingArgs) { + SetDefaults_VolumeBindingArgs(in) +} From 5c7f602f48a2840beb78b63dd8ee55a050e225be Mon Sep 17 00:00:00 2001 From: ravisantoshgudimetla Date: Mon, 4 Oct 2021 13:53:32 -0400 Subject: [PATCH 3/5] Make v1beta3 default --- cmd/kube-scheduler/app/options/configfile.go | 5 +- .../app/options/options_test.go | 400 ++++++++++++- cmd/kube-scheduler/app/server_test.go | 2 +- pkg/scheduler/apis/config/latest/latest.go | 6 +- pkg/scheduler/apis/config/scheme/scheme.go | 6 +- .../apis/config/scheme/scheme_test.go | 561 ++++++++++++++++++ pkg/scheduler/apis/config/testing/config.go | 13 + .../apis/config/testing/defaults/defaults.go | 137 +++++ .../apis/config/validation/validation.go | 5 + .../apis/config/validation/validation_test.go | 309 +++++++++- pkg/scheduler/scheduler.go | 4 +- 11 files changed, 1422 insertions(+), 26 deletions(-) diff --git a/cmd/kube-scheduler/app/options/configfile.go b/cmd/kube-scheduler/app/options/configfile.go index eda49fcfed9b6..8727c1c62f2c4 100644 --- a/cmd/kube-scheduler/app/options/configfile.go +++ b/cmd/kube-scheduler/app/options/configfile.go @@ -28,6 +28,7 @@ import ( "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" configv1beta2 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta2" + configv1beta3 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta3" ) func loadConfigFromFile(file string) (*config.KubeSchedulerConfiguration, error) { @@ -68,8 +69,10 @@ func encodeConfig(cfg *config.KubeSchedulerConfiguration) (*bytes.Buffer, error) switch cfg.TypeMeta.APIVersion { case configv1beta2.SchemeGroupVersion.String(): encoder = scheme.Codecs.EncoderForVersion(info.Serializer, configv1beta2.SchemeGroupVersion) + case configv1beta3.SchemeGroupVersion.String(): + encoder = scheme.Codecs.EncoderForVersion(info.Serializer, configv1beta3.SchemeGroupVersion) default: - encoder = scheme.Codecs.EncoderForVersion(info.Serializer, configv1beta2.SchemeGroupVersion) + encoder = scheme.Codecs.EncoderForVersion(info.Serializer, configv1beta3.SchemeGroupVersion) } if err := encoder.Encode(cfg, buf); err != nil { return buf, err diff --git a/cmd/kube-scheduler/app/options/options_test.go b/cmd/kube-scheduler/app/options/options_test.go index 5a8b696f3ec40..3683f99c3e2c5 100644 --- a/cmd/kube-scheduler/app/options/options_test.go +++ b/cmd/kube-scheduler/app/options/options_test.go @@ -36,8 +36,10 @@ import ( componentbaseconfig "k8s.io/component-base/config" "k8s.io/component-base/logs" "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kube-scheduler/config/v1beta3" kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config/latest" + configtesting "k8s.io/kubernetes/pkg/scheduler/apis/config/testing" "k8s.io/kubernetes/pkg/scheduler/apis/config/testing/defaults" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/names" ) @@ -77,7 +79,7 @@ func TestSchedulerOptions(t *testing.T) { configFile := filepath.Join(tmpDir, "scheduler.yaml") configKubeconfig := filepath.Join(tmpDir, "config.kubeconfig") if err := ioutil.WriteFile(configFile, []byte(fmt.Sprintf(` -apiVersion: kubescheduler.config.k8s.io/v1beta2 +apiVersion: kubescheduler.config.k8s.io/v1beta3 kind: KubeSchedulerConfiguration clientConnection: kubeconfig: "%s" @@ -118,6 +120,17 @@ leaderElection: t.Fatal(err) } + v1beta2VersionConfig := filepath.Join(tmpDir, "scheduler_v1beta2_api_version.yaml") + if err := ioutil.WriteFile(v1beta2VersionConfig, []byte(fmt.Sprintf(` +apiVersion: kubescheduler.config.k8s.io/v1beta2 +kind: KubeSchedulerConfiguration +clientConnection: + kubeconfig: "%s" +leaderElection: + leaderElect: true`, configKubeconfig)), os.FileMode(0600)); err != nil { + t.Fatal(err) + } + unknownVersionConfig := filepath.Join(tmpDir, "scheduler_invalid_wrong_api_version.yaml") if err := ioutil.WriteFile(unknownVersionConfig, []byte(fmt.Sprintf(` apiVersion: kubescheduler.config.k8s.io/unknown @@ -190,6 +203,37 @@ users: // plugin config pluginConfigFile := filepath.Join(tmpDir, "plugin.yaml") if err := ioutil.WriteFile(pluginConfigFile, []byte(fmt.Sprintf(` +apiVersion: kubescheduler.config.k8s.io/v1beta3 +kind: KubeSchedulerConfiguration +clientConnection: + kubeconfig: "%s" +profiles: +- plugins: + reserve: + enabled: + - name: foo + - name: bar + disabled: + - name: VolumeBinding + preBind: + enabled: + - name: foo + disabled: + - name: VolumeBinding + pluginConfig: + - name: InterPodAffinity + args: + hardPodAffinityWeight: 2 + - name: foo + args: + bar: baz +`, configKubeconfig)), os.FileMode(0600)); err != nil { + t.Fatal(err) + } + + // v1beta2 plugin config + v1beta2PluginConfigFile := filepath.Join(tmpDir, "v1beta2_plugin.yaml") + if err := ioutil.WriteFile(v1beta2PluginConfigFile, []byte(fmt.Sprintf(` apiVersion: kubescheduler.config.k8s.io/v1beta2 kind: KubeSchedulerConfiguration clientConnection: @@ -221,6 +265,33 @@ profiles: // multiple profiles config multiProfilesConfig := filepath.Join(tmpDir, "multi-profiles.yaml") if err := ioutil.WriteFile(multiProfilesConfig, []byte(fmt.Sprintf(` +apiVersion: kubescheduler.config.k8s.io/v1beta3 +kind: KubeSchedulerConfiguration +clientConnection: + kubeconfig: "%s" +profiles: +- schedulerName: "foo-profile" + plugins: + reserve: + enabled: + - name: foo + - name: VolumeBinding + disabled: + - name: VolumeBinding +- schedulerName: "bar-profile" + plugins: + preBind: + disabled: + - name: VolumeBinding + pluginConfig: + - name: foo +`, configKubeconfig)), os.FileMode(0600)); err != nil { + t.Fatal(err) + } + + // multiple profiles config + v1beta2MultiProfilesConfig := filepath.Join(tmpDir, "v1beta2_multi-profiles.yaml") + if err := ioutil.WriteFile(v1beta2MultiProfilesConfig, []byte(fmt.Sprintf(` apiVersion: kubescheduler.config.k8s.io/v1beta2 kind: KubeSchedulerConfiguration clientConnection: @@ -266,14 +337,83 @@ profiles: checkErrFn func(err error) bool }{ { - name: "v1beta2 config file", + name: "v1beta3 config file", options: &Options{ ConfigFile: configFile, ComponentConfig: func() kubeschedulerconfig.KubeSchedulerConfiguration { - cfg, err := latest.Default() - if err != nil { - t.Fatal(err) - } + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{}) + return *cfg + }(), + SecureServing: (&apiserveroptions.SecureServingOptions{ + ServerCert: apiserveroptions.GeneratableKeyCert{ + CertDirectory: "/a/b/c", + PairName: "kube-scheduler", + }, + HTTP2MaxStreamsPerConnection: 47, + }).WithLoopback(), + Authentication: &apiserveroptions.DelegatingAuthenticationOptions{ + CacheTTL: 10 * time.Second, + ClientCert: apiserveroptions.ClientCertAuthenticationOptions{}, + RequestHeader: apiserveroptions.RequestHeaderAuthenticationOptions{ + UsernameHeaders: []string{"x-remote-user"}, + GroupHeaders: []string{"x-remote-group"}, + ExtraHeaderPrefixes: []string{"x-remote-extra-"}, + }, + RemoteKubeConfigFileOptional: true, + }, + Authorization: &apiserveroptions.DelegatingAuthorizationOptions{ + AllowCacheTTL: 10 * time.Second, + DenyCacheTTL: 10 * time.Second, + RemoteKubeConfigFileOptional: true, + AlwaysAllowPaths: []string{"/healthz", "/readyz", "/livez"}, // note: this does not match /healthz/ or /healthz/* + AlwaysAllowGroups: []string{"system:masters"}, + }, + Logs: logs.NewOptions(), + }, + expectedUsername: "config", + expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta3.SchemeGroupVersion.String(), + }, + Parallelism: 16, + DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ + EnableProfiling: true, + EnableContentionProfiling: true, + }, + LeaderElection: componentbaseconfig.LeaderElectionConfiguration{ + LeaderElect: true, + LeaseDuration: metav1.Duration{Duration: 15 * time.Second}, + RenewDeadline: metav1.Duration{Duration: 10 * time.Second}, + RetryPeriod: metav1.Duration{Duration: 2 * time.Second}, + ResourceLock: "leases", + ResourceNamespace: "kube-system", + ResourceName: "kube-scheduler", + }, + ClientConnection: componentbaseconfig.ClientConnectionConfiguration{ + Kubeconfig: configKubeconfig, + QPS: 50, + Burst: 100, + ContentType: "application/vnd.kubernetes.protobuf", + }, + PercentageOfNodesToScore: defaultPercentageOfNodesToScore, + PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds, + PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds, + Profiles: []kubeschedulerconfig.KubeSchedulerProfile{ + { + SchedulerName: "default-scheduler", + Plugins: defaults.PluginsV1beta3, + PluginConfig: defaults.PluginConfigsV1beta3, + }, + }, + }, + }, + + { + name: "v1beta2 config file", + options: &Options{ + ConfigFile: v1beta2VersionConfig, + ComponentConfig: func() kubeschedulerconfig.KubeSchedulerConfiguration { + cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{}) return *cfg }(), SecureServing: (&apiserveroptions.SecureServingOptions{ @@ -407,7 +547,7 @@ profiles: expectedUsername: "flag", expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ TypeMeta: metav1.TypeMeta{ - APIVersion: v1beta2.SchemeGroupVersion.String(), + APIVersion: v1beta3.SchemeGroupVersion.String(), }, Parallelism: 16, DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ @@ -435,8 +575,8 @@ profiles: Profiles: []kubeschedulerconfig.KubeSchedulerProfile{ { SchedulerName: "default-scheduler", - Plugins: defaults.PluginsV1beta2, - PluginConfig: defaults.PluginConfigsV1beta2, + Plugins: defaults.PluginsV1beta3, + PluginConfig: defaults.PluginConfigsV1beta3, }, }, }, @@ -477,7 +617,7 @@ profiles: }, expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ TypeMeta: metav1.TypeMeta{ - APIVersion: v1beta2.SchemeGroupVersion.String(), + APIVersion: v1beta3.SchemeGroupVersion.String(), }, Parallelism: 16, DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ @@ -505,8 +645,8 @@ profiles: Profiles: []kubeschedulerconfig.KubeSchedulerProfile{ { SchedulerName: "default-scheduler", - Plugins: defaults.PluginsV1beta2, - PluginConfig: defaults.PluginConfigsV1beta2, + Plugins: defaults.PluginsV1beta3, + PluginConfig: defaults.PluginConfigsV1beta3, }, }, }, @@ -519,6 +659,120 @@ profiles: Logs: logs.NewOptions(), }, expectedUsername: "config", + expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta3.SchemeGroupVersion.String(), + }, + Parallelism: 16, + DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ + EnableProfiling: true, + EnableContentionProfiling: true, + }, + LeaderElection: componentbaseconfig.LeaderElectionConfiguration{ + LeaderElect: true, + LeaseDuration: metav1.Duration{Duration: 15 * time.Second}, + RenewDeadline: metav1.Duration{Duration: 10 * time.Second}, + RetryPeriod: metav1.Duration{Duration: 2 * time.Second}, + ResourceLock: "leases", + ResourceNamespace: "kube-system", + ResourceName: "kube-scheduler", + }, + ClientConnection: componentbaseconfig.ClientConnectionConfiguration{ + Kubeconfig: configKubeconfig, + QPS: 50, + Burst: 100, + ContentType: "application/vnd.kubernetes.protobuf", + }, + PercentageOfNodesToScore: defaultPercentageOfNodesToScore, + PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds, + PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds, + Profiles: []kubeschedulerconfig.KubeSchedulerProfile{ + { + SchedulerName: "default-scheduler", + Plugins: &kubeschedulerconfig.Plugins{ + QueueSort: defaults.PluginsV1beta3.QueueSort, + PreFilter: defaults.PluginsV1beta3.PreFilter, + Filter: defaults.PluginsV1beta3.Filter, + PostFilter: defaults.PluginsV1beta3.PostFilter, + PreScore: defaults.PluginsV1beta3.PreScore, + Score: defaults.PluginsV1beta3.Score, + Reserve: kubeschedulerconfig.PluginSet{ + Enabled: []kubeschedulerconfig.Plugin{ + {Name: "foo"}, + {Name: "bar"}, + }, + }, + PreBind: kubeschedulerconfig.PluginSet{ + Enabled: []kubeschedulerconfig.Plugin{ + {Name: "foo"}, + }, + }, + Bind: defaults.PluginsV1beta3.Bind, + }, + PluginConfig: []kubeschedulerconfig.PluginConfig{ + { + Name: "InterPodAffinity", + Args: &kubeschedulerconfig.InterPodAffinityArgs{ + HardPodAffinityWeight: 2, + }, + }, + { + Name: "foo", + Args: &runtime.Unknown{ + Raw: []byte(`{"bar":"baz"}`), + ContentType: "application/json", + }, + }, + { + Name: "DefaultPreemption", + Args: &kubeschedulerconfig.DefaultPreemptionArgs{ + MinCandidateNodesPercentage: 10, + MinCandidateNodesAbsolute: 100, + }, + }, + { + Name: "NodeAffinity", + Args: &kubeschedulerconfig.NodeAffinityArgs{}, + }, + { + Name: "NodeResourcesBalancedAllocation", + Args: &kubeschedulerconfig.NodeResourcesBalancedAllocationArgs{ + Resources: []kubeschedulerconfig.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }, + }, + { + Name: "NodeResourcesFit", + Args: &kubeschedulerconfig.NodeResourcesFitArgs{ + ScoringStrategy: &kubeschedulerconfig.ScoringStrategy{ + Type: kubeschedulerconfig.LeastAllocated, + Resources: []kubeschedulerconfig.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }, + }, + }, + { + Name: "PodTopologySpread", + Args: &kubeschedulerconfig.PodTopologySpreadArgs{ + DefaultingType: kubeschedulerconfig.SystemDefaulting, + }, + }, + { + Name: "VolumeBinding", + Args: &kubeschedulerconfig.VolumeBindingArgs{ + BindTimeoutSeconds: 600, + }, + }, + }, + }, + }, + }, + }, + { + name: "v1beta2 plugin config", + options: &Options{ + ConfigFile: v1beta2PluginConfigFile, + Logs: logs.NewOptions(), + }, + expectedUsername: "config", expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ TypeMeta: metav1.TypeMeta{ APIVersion: v1beta2.SchemeGroupVersion.String(), @@ -633,6 +887,126 @@ profiles: Logs: logs.NewOptions(), }, expectedUsername: "config", + expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta3.SchemeGroupVersion.String(), + }, + Parallelism: 16, + DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ + EnableProfiling: true, + EnableContentionProfiling: true, + }, + LeaderElection: componentbaseconfig.LeaderElectionConfiguration{ + LeaderElect: true, + LeaseDuration: metav1.Duration{Duration: 15 * time.Second}, + RenewDeadline: metav1.Duration{Duration: 10 * time.Second}, + RetryPeriod: metav1.Duration{Duration: 2 * time.Second}, + ResourceLock: "leases", + ResourceNamespace: "kube-system", + ResourceName: "kube-scheduler", + }, + ClientConnection: componentbaseconfig.ClientConnectionConfiguration{ + Kubeconfig: configKubeconfig, + QPS: 50, + Burst: 100, + ContentType: "application/vnd.kubernetes.protobuf", + }, + PercentageOfNodesToScore: defaultPercentageOfNodesToScore, + PodInitialBackoffSeconds: defaultPodInitialBackoffSeconds, + PodMaxBackoffSeconds: defaultPodMaxBackoffSeconds, + Profiles: []kubeschedulerconfig.KubeSchedulerProfile{ + { + SchedulerName: "foo-profile", + Plugins: &kubeschedulerconfig.Plugins{ + QueueSort: defaults.PluginsV1beta3.QueueSort, + PreFilter: defaults.PluginsV1beta3.PreFilter, + Filter: defaults.PluginsV1beta3.Filter, + PostFilter: defaults.PluginsV1beta3.PostFilter, + PreScore: defaults.PluginsV1beta3.PreScore, + Score: defaults.PluginsV1beta3.Score, + Bind: defaults.PluginsV1beta3.Bind, + PreBind: defaults.PluginsV1beta3.PreBind, + Reserve: kubeschedulerconfig.PluginSet{ + Enabled: []kubeschedulerconfig.Plugin{ + {Name: "foo"}, + {Name: names.VolumeBinding}, + }, + }, + }, + PluginConfig: defaults.PluginConfigsV1beta3, + }, + { + SchedulerName: "bar-profile", + Plugins: &kubeschedulerconfig.Plugins{ + QueueSort: defaults.PluginsV1beta3.QueueSort, + PreFilter: defaults.PluginsV1beta3.PreFilter, + Filter: defaults.PluginsV1beta3.Filter, + PostFilter: defaults.PluginsV1beta3.PostFilter, + PreScore: defaults.PluginsV1beta3.PreScore, + Score: defaults.PluginsV1beta3.Score, + Bind: defaults.PluginsV1beta3.Bind, + Reserve: defaults.PluginsV1beta3.Reserve, + }, + PluginConfig: []kubeschedulerconfig.PluginConfig{ + { + Name: "foo", + }, + { + Name: "DefaultPreemption", + Args: &kubeschedulerconfig.DefaultPreemptionArgs{ + MinCandidateNodesPercentage: 10, + MinCandidateNodesAbsolute: 100, + }, + }, + { + Name: "InterPodAffinity", + Args: &kubeschedulerconfig.InterPodAffinityArgs{ + HardPodAffinityWeight: 1, + }, + }, + { + Name: "NodeAffinity", + Args: &kubeschedulerconfig.NodeAffinityArgs{}, + }, + { + Name: "NodeResourcesBalancedAllocation", + Args: &kubeschedulerconfig.NodeResourcesBalancedAllocationArgs{ + Resources: []kubeschedulerconfig.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }, + }, + { + Name: "NodeResourcesFit", + Args: &kubeschedulerconfig.NodeResourcesFitArgs{ + ScoringStrategy: &kubeschedulerconfig.ScoringStrategy{ + Type: kubeschedulerconfig.LeastAllocated, + Resources: []kubeschedulerconfig.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }, + }, + }, + { + Name: "PodTopologySpread", + Args: &kubeschedulerconfig.PodTopologySpreadArgs{ + DefaultingType: kubeschedulerconfig.SystemDefaulting, + }, + }, + { + Name: "VolumeBinding", + Args: &kubeschedulerconfig.VolumeBindingArgs{ + BindTimeoutSeconds: 600, + }, + }, + }, + }, + }, + }, + }, + { + name: "v1beta2 multiple profiles", + options: &Options{ + ConfigFile: v1beta2MultiProfilesConfig, + Logs: logs.NewOptions(), + }, + expectedUsername: "config", expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ TypeMeta: metav1.TypeMeta{ APIVersion: v1beta2.SchemeGroupVersion.String(), @@ -758,7 +1132,7 @@ profiles: expectedUsername: "config", expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ TypeMeta: metav1.TypeMeta{ - APIVersion: v1beta2.SchemeGroupVersion.String(), + APIVersion: v1beta3.SchemeGroupVersion.String(), }, Parallelism: 16, DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ diff --git a/cmd/kube-scheduler/app/server_test.go b/cmd/kube-scheduler/app/server_test.go index 0b02194202610..5d335561150ae 100644 --- a/cmd/kube-scheduler/app/server_test.go +++ b/cmd/kube-scheduler/app/server_test.go @@ -163,7 +163,7 @@ profiles: "--kubeconfig", configKubeconfig, }, wantPlugins: map[string]*config.Plugins{ - "default-scheduler": defaults.PluginsV1beta2, + "default-scheduler": defaults.PluginsV1beta3, }, }, { diff --git a/pkg/scheduler/apis/config/latest/latest.go b/pkg/scheduler/apis/config/latest/latest.go index b9fb3ff186b87..1833b873fe97e 100644 --- a/pkg/scheduler/apis/config/latest/latest.go +++ b/pkg/scheduler/apis/config/latest/latest.go @@ -18,7 +18,7 @@ package latest import ( "k8s.io/component-base/config/v1alpha1" - "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kube-scheduler/config/v1beta3" "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" ) @@ -26,7 +26,7 @@ import ( // Default creates a default configuration of the latest versioned type. // This function needs to be updated whenever we bump the scheduler's component config version. func Default() (*config.KubeSchedulerConfiguration, error) { - versionedCfg := v1beta2.KubeSchedulerConfiguration{} + versionedCfg := v1beta3.KubeSchedulerConfiguration{} versionedCfg.DebuggingConfiguration = *v1alpha1.NewRecommendedDebuggingConfiguration() scheme.Scheme.Default(&versionedCfg) @@ -38,6 +38,6 @@ func Default() (*config.KubeSchedulerConfiguration, error) { // because the field will be cleared later by API machinery during // conversion. See KubeSchedulerConfiguration internal type definition for // more details. - cfg.TypeMeta.APIVersion = v1beta2.SchemeGroupVersion.String() + cfg.TypeMeta.APIVersion = v1beta3.SchemeGroupVersion.String() return &cfg, nil } diff --git a/pkg/scheduler/apis/config/scheme/scheme.go b/pkg/scheduler/apis/config/scheme/scheme.go index 99806b7e9bfad..ac9effee02d96 100644 --- a/pkg/scheduler/apis/config/scheme/scheme.go +++ b/pkg/scheduler/apis/config/scheme/scheme.go @@ -23,6 +23,7 @@ import ( config "k8s.io/kubernetes/pkg/scheduler/apis/config" configv1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1" configv1beta2 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta2" + configv1beta3 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta3" ) var ( @@ -42,5 +43,8 @@ func AddToScheme(scheme *runtime.Scheme) { utilruntime.Must(config.AddToScheme(scheme)) utilruntime.Must(configv1.AddToScheme(scheme)) utilruntime.Must(configv1beta2.AddToScheme(scheme)) - utilruntime.Must(scheme.SetVersionPriority(configv1beta2.SchemeGroupVersion)) + utilruntime.Must(configv1beta3.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority( + configv1beta3.SchemeGroupVersion, + configv1beta2.SchemeGroupVersion)) } diff --git a/pkg/scheduler/apis/config/scheme/scheme_test.go b/pkg/scheduler/apis/config/scheme/scheme_test.go index 5a70eb6262dc1..fca416ede0c77 100644 --- a/pkg/scheduler/apis/config/scheme/scheme_test.go +++ b/pkg/scheduler/apis/config/scheme/scheme_test.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kube-scheduler/config/v1beta3" "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config/testing/defaults" "k8s.io/utils/pointer" @@ -381,6 +382,347 @@ profiles: }, }, }, + // v1beta3 tests + { + name: "v1beta3 all plugin args in default profile", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta3 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: DefaultPreemption + args: + minCandidateNodesPercentage: 50 + minCandidateNodesAbsolute: 500 + - name: InterPodAffinity + args: + hardPodAffinityWeight: 5 + - name: NodeResourcesFit + args: + ignoredResources: ["foo"] + - name: PodTopologySpread + args: + defaultConstraints: + - maxSkew: 1 + topologyKey: zone + whenUnsatisfiable: ScheduleAnyway + - name: VolumeBinding + args: + bindTimeoutSeconds: 300 + - name: NodeAffinity + args: + addedAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: foo + operator: In + values: ["bar"] + - name: NodeResourcesBalancedAllocation + args: + resources: + - name: cpu # default weight(1) will be set. + - name: memory # weight 0 will be replaced by 1. + weight: 0 + - name: scalar0 + weight: 1 + - name: scalar1 # default weight(1) will be set for scalar1 + - name: scalar2 # weight 0 will be replaced by 1. + weight: 0 + - name: scalar3 + weight: 2 +`), + wantProfiles: []config.KubeSchedulerProfile{ + { + SchedulerName: "default-scheduler", + Plugins: defaults.PluginsV1beta3, + PluginConfig: []config.PluginConfig{ + { + Name: "DefaultPreemption", + Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 50, MinCandidateNodesAbsolute: 500}, + }, + { + Name: "InterPodAffinity", + Args: &config.InterPodAffinityArgs{HardPodAffinityWeight: 5}, + }, + { + Name: "NodeResourcesFit", + Args: &config.NodeResourcesFitArgs{ + IgnoredResources: []string{"foo"}, + ScoringStrategy: &config.ScoringStrategy{ + Type: config.LeastAllocated, + Resources: []config.ResourceSpec{ + {Name: "cpu", Weight: 1}, + {Name: "memory", Weight: 1}, + }, + }, + }, + }, + { + Name: "PodTopologySpread", + Args: &config.PodTopologySpreadArgs{ + DefaultConstraints: []corev1.TopologySpreadConstraint{ + {MaxSkew: 1, TopologyKey: "zone", WhenUnsatisfiable: corev1.ScheduleAnyway}, + }, + DefaultingType: config.SystemDefaulting, + }, + }, + { + Name: "VolumeBinding", + Args: &config.VolumeBindingArgs{ + BindTimeoutSeconds: 300, + }, + }, + { + Name: "NodeAffinity", + Args: &config.NodeAffinityArgs{ + AddedAffinity: &corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "foo", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"bar"}, + }, + }, + }, + }, + }, + }, + }, + }, + { + Name: "NodeResourcesBalancedAllocation", + Args: &config.NodeResourcesBalancedAllocationArgs{ + Resources: []config.ResourceSpec{ + {Name: "cpu", Weight: 1}, + {Name: "memory", Weight: 1}, + {Name: "scalar0", Weight: 1}, + {Name: "scalar1", Weight: 1}, + {Name: "scalar2", Weight: 1}, + {Name: "scalar3", Weight: 2}}, + }, + }, + }, + }, + }, + }, + { + name: "v1beta3 plugins can include version and kind", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta3 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: DefaultPreemption + args: + apiVersion: kubescheduler.config.k8s.io/v1beta3 + kind: DefaultPreemptionArgs + minCandidateNodesPercentage: 50 +`), + wantProfiles: []config.KubeSchedulerProfile{ + { + SchedulerName: "default-scheduler", + Plugins: defaults.PluginsV1beta3, + PluginConfig: []config.PluginConfig{ + { + Name: "DefaultPreemption", + Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 50, MinCandidateNodesAbsolute: 100}, + }, + { + Name: "InterPodAffinity", + Args: &config.InterPodAffinityArgs{ + HardPodAffinityWeight: 1, + }, + }, + { + Name: "NodeAffinity", + Args: &config.NodeAffinityArgs{}, + }, + { + Name: "NodeResourcesBalancedAllocation", + Args: &config.NodeResourcesBalancedAllocationArgs{ + Resources: []config.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }, + }, + { + Name: "NodeResourcesFit", + Args: &config.NodeResourcesFitArgs{ + ScoringStrategy: &config.ScoringStrategy{ + Type: config.LeastAllocated, + Resources: []config.ResourceSpec{ + {Name: "cpu", Weight: 1}, + {Name: "memory", Weight: 1}, + }, + }, + }, + }, + { + Name: "PodTopologySpread", + Args: &config.PodTopologySpreadArgs{ + DefaultingType: config.SystemDefaulting, + }, + }, + { + Name: "VolumeBinding", + Args: &config.VolumeBindingArgs{ + BindTimeoutSeconds: 600, + }, + }, + }, + }, + }, + }, + { + name: "plugin group and kind should match the type", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta3 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: DefaultPreemption + args: + apiVersion: kubescheduler.config.k8s.io/v1beta3 + kind: InterPodAffinityArgs +`), + wantErr: `decoding .profiles[0].pluginConfig[0]: args for plugin DefaultPreemption were not of type DefaultPreemptionArgs.kubescheduler.config.k8s.io, got InterPodAffinityArgs.kubescheduler.config.k8s.io`, + }, + { + name: "v1beta3 NodResourcesFitArgs shape encoding is strict", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta3 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: NodeResourcesFit + args: + scoringStrategy: + requestedToCapacityRatio: + shape: + - Score: 2 + Utilization: 1 +`), + wantErr: `decoding .profiles[0].pluginConfig[0]: decoding args for plugin NodeResourcesFit: strict decoder error for {"scoringStrategy":{"requestedToCapacityRatio":{"shape":[{"Score":2,"Utilization":1}]}}}: v1beta3.NodeResourcesFitArgs.ScoringStrategy: v1beta3.ScoringStrategy.RequestedToCapacityRatio: v1beta3.RequestedToCapacityRatioParam.Shape: []v1beta3.UtilizationShapePoint: v1beta3.UtilizationShapePoint.ReadObject: found unknown field: Score, error found in #10 byte of ...|:[{"Score":2,"Utiliz|..., bigger context ...|gy":{"requestedToCapacityRatio":{"shape":[{"Score":2,"Utilization":1}]}}}|...`, + }, + { + name: "v1beta3 NodeResourcesFitArgs resources encoding is strict", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta3 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: NodeResourcesFit + args: + scoringStrategy: + resources: + - Name: cpu + Weight: 1 +`), + wantErr: `decoding .profiles[0].pluginConfig[0]: decoding args for plugin NodeResourcesFit: strict decoder error for {"scoringStrategy":{"resources":[{"Name":"cpu","Weight":1}]}}: v1beta3.NodeResourcesFitArgs.ScoringStrategy: v1beta3.ScoringStrategy.Resources: []v1beta3.ResourceSpec: v1beta3.ResourceSpec.ReadObject: found unknown field: Name, error found in #10 byte of ...|":[{"Name":"cpu","We|..., bigger context ...|{"scoringStrategy":{"resources":[{"Name":"cpu","Weight":1}]}}|...`, + }, + { + name: "out-of-tree plugin args", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta3 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: OutOfTreePlugin + args: + foo: bar +`), + wantProfiles: []config.KubeSchedulerProfile{ + { + SchedulerName: "default-scheduler", + Plugins: defaults.PluginsV1beta3, + PluginConfig: append([]config.PluginConfig{ + { + Name: "OutOfTreePlugin", + Args: &runtime.Unknown{ + ContentType: "application/json", + Raw: []byte(`{"foo":"bar"}`), + }, + }, + }, defaults.PluginConfigsV1beta3...), + }, + }, + }, + { + name: "empty and no plugin args", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta3 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: DefaultPreemption + args: + - name: InterPodAffinity + args: + - name: NodeResourcesFit + - name: OutOfTreePlugin + args: + - name: VolumeBinding + args: + - name: PodTopologySpread + - name: NodeAffinity + - name: NodeResourcesBalancedAllocation +`), + wantProfiles: []config.KubeSchedulerProfile{ + { + SchedulerName: "default-scheduler", + Plugins: defaults.PluginsV1beta3, + PluginConfig: []config.PluginConfig{ + { + Name: "DefaultPreemption", + Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 10, MinCandidateNodesAbsolute: 100}, + }, + { + Name: "InterPodAffinity", + Args: &config.InterPodAffinityArgs{ + HardPodAffinityWeight: 1, + }, + }, + { + Name: "NodeResourcesFit", + Args: &config.NodeResourcesFitArgs{ + ScoringStrategy: &config.ScoringStrategy{ + Type: config.LeastAllocated, + Resources: []config.ResourceSpec{ + {Name: "cpu", Weight: 1}, + {Name: "memory", Weight: 1}, + }, + }, + }, + }, + {Name: "OutOfTreePlugin"}, + { + Name: "VolumeBinding", + Args: &config.VolumeBindingArgs{ + BindTimeoutSeconds: 600, + }, + }, + { + Name: "PodTopologySpread", + Args: &config.PodTopologySpreadArgs{ + DefaultingType: config.SystemDefaulting, + }, + }, + { + Name: "NodeAffinity", + Args: &config.NodeAffinityArgs{}, + }, + { + Name: "NodeResourcesBalancedAllocation", + Args: &config.NodeResourcesBalancedAllocationArgs{ + Resources: []config.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }, + }, + }, + }, + }, + }, } decoder := Codecs.UniversalDecoder() for _, tt := range testCases { @@ -632,6 +974,225 @@ profiles: foo: bar name: OutOfTreePlugin schedulerName: "" +`, + }, + //v1beta3 tests + { + name: "v1beta3 in-tree and out-of-tree plugins", + version: v1beta3.SchemeGroupVersion, + obj: &v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{ + { + PluginConfig: []v1beta3.PluginConfig{ + { + Name: "InterPodAffinity", + Args: runtime.RawExtension{ + Object: &v1beta3.InterPodAffinityArgs{ + HardPodAffinityWeight: pointer.Int32Ptr(5), + }, + }, + }, + { + Name: "VolumeBinding", + Args: runtime.RawExtension{ + Object: &v1beta2.VolumeBindingArgs{ + BindTimeoutSeconds: pointer.Int64Ptr(300), + Shape: []v1beta2.UtilizationShapePoint{ + { + Utilization: 0, + Score: 0, + }, + { + Utilization: 100, + Score: 10, + }, + }, + }, + }, + }, + { + Name: "NodeResourcesFit", + Args: runtime.RawExtension{ + Object: &v1beta3.NodeResourcesFitArgs{ + ScoringStrategy: &v1beta3.ScoringStrategy{ + Type: v1beta3.RequestedToCapacityRatio, + Resources: []v1beta3.ResourceSpec{{Name: "cpu", Weight: 1}}, + RequestedToCapacityRatio: &v1beta3.RequestedToCapacityRatioParam{ + Shape: []v1beta3.UtilizationShapePoint{ + {Utilization: 1, Score: 2}, + }, + }, + }, + }, + }, + }, + { + Name: "PodTopologySpread", + Args: runtime.RawExtension{ + Object: &v1beta3.PodTopologySpreadArgs{ + DefaultConstraints: []corev1.TopologySpreadConstraint{}, + }, + }, + }, + { + Name: "OutOfTreePlugin", + Args: runtime.RawExtension{ + Raw: []byte(`{"foo":"bar"}`), + }, + }, + }, + }, + }, + }, + want: `apiVersion: kubescheduler.config.k8s.io/v1beta3 +clientConnection: + acceptContentTypes: "" + burst: 0 + contentType: "" + kubeconfig: "" + qps: 0 +kind: KubeSchedulerConfiguration +leaderElection: + leaderElect: null + leaseDuration: 0s + renewDeadline: 0s + resourceLock: "" + resourceName: "" + resourceNamespace: "" + retryPeriod: 0s +profiles: +- pluginConfig: + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta3 + hardPodAffinityWeight: 5 + kind: InterPodAffinityArgs + name: InterPodAffinity + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta3 + bindTimeoutSeconds: 300 + kind: VolumeBindingArgs + shape: + - score: 0 + utilization: 0 + - score: 10 + utilization: 100 + name: VolumeBinding + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta3 + kind: NodeResourcesFitArgs + scoringStrategy: + requestedToCapacityRatio: + shape: + - score: 2 + utilization: 1 + resources: + - name: cpu + weight: 1 + type: RequestedToCapacityRatio + name: NodeResourcesFit + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta3 + kind: PodTopologySpreadArgs + name: PodTopologySpread + - args: + foo: bar + name: OutOfTreePlugin +`, + }, + { + name: "v1beta3 in-tree and out-of-tree plugins from internal", + version: v1beta3.SchemeGroupVersion, + obj: &config.KubeSchedulerConfiguration{ + Parallelism: 8, + Profiles: []config.KubeSchedulerProfile{ + { + PluginConfig: []config.PluginConfig{ + { + Name: "InterPodAffinity", + Args: &config.InterPodAffinityArgs{ + HardPodAffinityWeight: 5, + }, + }, + { + Name: "NodeResourcesFit", + Args: &config.NodeResourcesFitArgs{ + ScoringStrategy: &config.ScoringStrategy{ + Type: config.LeastAllocated, + Resources: []config.ResourceSpec{{Name: "cpu", Weight: 1}}, + }, + }, + }, + { + Name: "VolumeBinding", + Args: &config.VolumeBindingArgs{ + BindTimeoutSeconds: 300, + }, + }, + { + Name: "PodTopologySpread", + Args: &config.PodTopologySpreadArgs{}, + }, + { + Name: "OutOfTreePlugin", + Args: &runtime.Unknown{ + Raw: []byte(`{"foo":"bar"}`), + }, + }, + }, + }, + }, + }, + want: `apiVersion: kubescheduler.config.k8s.io/v1beta3 +clientConnection: + acceptContentTypes: "" + burst: 0 + contentType: "" + kubeconfig: "" + qps: 0 +enableContentionProfiling: false +enableProfiling: false +kind: KubeSchedulerConfiguration +leaderElection: + leaderElect: false + leaseDuration: 0s + renewDeadline: 0s + resourceLock: "" + resourceName: "" + resourceNamespace: "" + retryPeriod: 0s +parallelism: 8 +percentageOfNodesToScore: 0 +podInitialBackoffSeconds: 0 +podMaxBackoffSeconds: 0 +profiles: +- pluginConfig: + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta3 + hardPodAffinityWeight: 5 + kind: InterPodAffinityArgs + name: InterPodAffinity + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta3 + kind: NodeResourcesFitArgs + scoringStrategy: + resources: + - name: cpu + weight: 1 + type: LeastAllocated + name: NodeResourcesFit + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta3 + bindTimeoutSeconds: 300 + kind: VolumeBindingArgs + name: VolumeBinding + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta3 + kind: PodTopologySpreadArgs + name: PodTopologySpread + - args: + foo: bar + name: OutOfTreePlugin + schedulerName: "" `, }, } diff --git a/pkg/scheduler/apis/config/testing/config.go b/pkg/scheduler/apis/config/testing/config.go index 6b23b8a8a7c62..c564fc55cafa4 100644 --- a/pkg/scheduler/apis/config/testing/config.go +++ b/pkg/scheduler/apis/config/testing/config.go @@ -21,6 +21,7 @@ import ( "k8s.io/component-base/config/v1alpha1" "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kube-scheduler/config/v1beta3" "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" ) @@ -36,3 +37,15 @@ func V1beta2ToInternalWithDefaults(t *testing.T, versionedCfg v1beta2.KubeSchedu } return &cfg } + +// V1beta3ToInternalWithDefaults creates a v1beta3 default configuration. +func V1beta3ToInternalWithDefaults(t *testing.T, versionedCfg v1beta3.KubeSchedulerConfiguration) *config.KubeSchedulerConfiguration { + versionedCfg.DebuggingConfiguration = *v1alpha1.NewRecommendedDebuggingConfiguration() + + scheme.Scheme.Default(&versionedCfg) + cfg := config.KubeSchedulerConfiguration{} + if err := scheme.Scheme.Convert(&versionedCfg, &cfg, nil); err != nil { + t.Fatal(err) + } + return &cfg +} diff --git a/pkg/scheduler/apis/config/testing/defaults/defaults.go b/pkg/scheduler/apis/config/testing/defaults/defaults.go index 8d21751d5af47..d5da971e97721 100644 --- a/pkg/scheduler/apis/config/testing/defaults/defaults.go +++ b/pkg/scheduler/apis/config/testing/defaults/defaults.go @@ -287,3 +287,140 @@ var PluginConfigsV1beta2 = []config.PluginConfig{ }, }, } + +// PluginsV1beta3 default set of v1beta3 plugins. +var PluginsV1beta3 = &config.Plugins{ + QueueSort: config.PluginSet{ + Enabled: []config.Plugin{ + {Name: names.PrioritySort}, + }, + }, + PreFilter: config.PluginSet{ + Enabled: []config.Plugin{ + {Name: names.NodeResourcesFit}, + {Name: names.NodePorts}, + {Name: names.VolumeRestrictions}, + {Name: names.PodTopologySpread}, + {Name: names.InterPodAffinity}, + {Name: names.VolumeBinding}, + {Name: names.NodeAffinity}, + }, + }, + Filter: config.PluginSet{ + Enabled: []config.Plugin{ + {Name: names.NodeUnschedulable}, + {Name: names.NodeName}, + {Name: names.TaintToleration}, + {Name: names.NodeAffinity}, + {Name: names.NodePorts}, + {Name: names.NodeResourcesFit}, + {Name: names.VolumeRestrictions}, + {Name: names.EBSLimits}, + {Name: names.GCEPDLimits}, + {Name: names.NodeVolumeLimits}, + {Name: names.AzureDiskLimits}, + {Name: names.VolumeBinding}, + {Name: names.VolumeZone}, + {Name: names.PodTopologySpread}, + {Name: names.InterPodAffinity}, + }, + }, + PostFilter: config.PluginSet{ + Enabled: []config.Plugin{ + {Name: names.DefaultPreemption}, + }, + }, + PreScore: config.PluginSet{ + Enabled: []config.Plugin{ + {Name: names.InterPodAffinity}, + {Name: names.PodTopologySpread}, + {Name: names.TaintToleration}, + {Name: names.NodeAffinity}, + }, + }, + Score: config.PluginSet{ + Enabled: []config.Plugin{ + {Name: names.NodeResourcesBalancedAllocation, Weight: 1}, + {Name: names.ImageLocality, Weight: 1}, + {Name: names.NodeResourcesFit, Weight: 1}, + // Weight is doubled because: + // - This is a score coming from user preference. + {Name: names.InterPodAffinity, Weight: 2}, + // Weight is doubled because: + // - This is a score coming from user preference. + {Name: names.NodeAffinity, Weight: 2}, + // Weight is doubled because: + // - This is a score coming from user preference. + // - It makes its signal comparable to NodeResourcesLeastAllocated. + {Name: names.PodTopologySpread, Weight: 2}, + // Weight is tripled because: + // - This is a score coming from user preference. + // - Usage of node tainting to group nodes in the cluster is increasing becoming a use-case + // for many user workloads + {Name: names.TaintToleration, Weight: 3}, + }, + }, + Reserve: config.PluginSet{ + Enabled: []config.Plugin{ + {Name: names.VolumeBinding}, + }, + }, + PreBind: config.PluginSet{ + Enabled: []config.Plugin{ + {Name: names.VolumeBinding}, + }, + }, + Bind: config.PluginSet{ + Enabled: []config.Plugin{ + {Name: names.DefaultBinder}, + }, + }, +} + +// PluginConfigsV1beta3 default plugin configurations. +var PluginConfigsV1beta3 = []config.PluginConfig{ + { + Name: "DefaultPreemption", + Args: &config.DefaultPreemptionArgs{ + MinCandidateNodesPercentage: 10, + MinCandidateNodesAbsolute: 100, + }, + }, + { + Name: "InterPodAffinity", + Args: &config.InterPodAffinityArgs{ + HardPodAffinityWeight: 1, + }, + }, + { + Name: "NodeAffinity", + Args: &config.NodeAffinityArgs{}, + }, + { + Name: "NodeResourcesBalancedAllocation", + Args: &config.NodeResourcesBalancedAllocationArgs{ + Resources: []config.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }, + }, + { + Name: "NodeResourcesFit", + Args: &config.NodeResourcesFitArgs{ + ScoringStrategy: &config.ScoringStrategy{ + Type: config.LeastAllocated, + Resources: []config.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }, + }, + }, + { + Name: "PodTopologySpread", + Args: &config.PodTopologySpreadArgs{ + DefaultingType: config.SystemDefaulting, + }, + }, + { + Name: "VolumeBinding", + Args: &config.VolumeBindingArgs{ + BindTimeoutSeconds: 600, + }, + }, +} diff --git a/pkg/scheduler/apis/config/validation/validation.go b/pkg/scheduler/apis/config/validation/validation.go index bb0a3b4fd0ad0..060d82a457d10 100644 --- a/pkg/scheduler/apis/config/validation/validation.go +++ b/pkg/scheduler/apis/config/validation/validation.go @@ -34,6 +34,7 @@ import ( v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta2" + "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta3" ) // ValidateKubeSchedulerConfiguration ensures validation of the KubeSchedulerConfiguration struct @@ -136,6 +137,10 @@ var removedPluginsByVersion = []removedPlugins{ "RequestedToCapacityRatio", }, }, + { + schemeGroupVersion: v1beta3.SchemeGroupVersion.String(), + plugins: []string{}, + }, } // isPluginRemoved checks if a given plugin was removed in the given component diff --git a/pkg/scheduler/apis/config/validation/validation_test.go b/pkg/scheduler/apis/config/validation/validation_test.go index cb5877e6222fd..9a6967a53e17a 100644 --- a/pkg/scheduler/apis/config/validation/validation_test.go +++ b/pkg/scheduler/apis/config/validation/validation_test.go @@ -26,9 +26,10 @@ import ( componentbaseconfig "k8s.io/component-base/config" "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta2" + "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta3" ) -func TestValidateKubeSchedulerConfiguration(t *testing.T) { +func TestValidateKubeSchedulerConfigurationV1beta2(t *testing.T) { podInitialBackoffSeconds := int64(1) podMaxBackoffSeconds := int64(1) validConfig := &config.KubeSchedulerConfiguration{ @@ -198,14 +199,312 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) { BindVerb: "bar", }) - badRemovedPlugins1 := validConfig.DeepCopy() // default v1beta2 + badRemovedPlugins1 := validConfig.DeepCopy() + badRemovedPlugins1.Profiles[0].Plugins.Score.Enabled = append(badRemovedPlugins1.Profiles[0].Plugins.Score.Enabled, config.Plugin{Name: "ServiceAffinity", Weight: 2}) + + badRemovedPlugins3 := validConfig.DeepCopy() + badRemovedPlugins3.Profiles[0].Plugins.Score.Enabled = append(badRemovedPlugins3.Profiles[0].Plugins.Score.Enabled, config.Plugin{Name: "NodeResourcesMostAllocated", Weight: 2}) + + goodRemovedPlugins2 := validConfig.DeepCopy() + goodRemovedPlugins2.Profiles[0].Plugins.Score.Enabled = append(goodRemovedPlugins2.Profiles[0].Plugins.Score.Enabled, config.Plugin{Name: "PodTopologySpread", Weight: 2}) + + deprecatedPluginsConfig := validConfig.DeepCopy() + deprecatedPluginsConfig.Profiles[0].PluginConfig = append(deprecatedPluginsConfig.Profiles[0].PluginConfig, config.PluginConfig{ + Name: "NodeResourcesLeastAllocated", + Args: &config.NodeResourcesLeastAllocatedArgs{}, + }) + + scenarios := map[string]struct { + expectedToFail bool + config *config.KubeSchedulerConfiguration + errorString string + }{ + "good": { + expectedToFail: false, + config: validConfig, + }, + "bad-parallelism-invalid-value": { + expectedToFail: true, + config: invalidParallelismValue, + }, + "bad-resource-name-not-set": { + expectedToFail: true, + config: resourceNameNotSet, + }, + "bad-resource-namespace-not-set": { + expectedToFail: true, + config: resourceNamespaceNotSet, + }, + "non-empty-metrics-bind-addr": { + expectedToFail: true, + config: metricsBindAddrInvalid, + }, + "non-empty-healthz-bind-addr": { + expectedToFail: true, + config: healthzBindAddrInvalid, + }, + "bad-percentage-of-nodes-to-score": { + expectedToFail: true, + config: percentageOfNodesToScore101, + }, + "scheduler-name-not-set": { + expectedToFail: true, + config: schedulerNameNotSet, + }, + "repeated-scheduler-name": { + expectedToFail: true, + config: repeatedSchedulerName, + }, + "different-queue-sort": { + expectedToFail: true, + config: differentQueueSort, + }, + "one-empty-queue-sort": { + expectedToFail: true, + config: oneEmptyQueueSort, + }, + "extender-negative-weight": { + expectedToFail: true, + config: extenderNegativeWeight, + }, + "extender-duplicate-managed-resources": { + expectedToFail: true, + config: extenderDuplicateManagedResource, + }, + "extender-duplicate-bind": { + expectedToFail: true, + config: extenderDuplicateBind, + }, + "invalid-node-percentage": { + expectedToFail: true, + config: invalidNodePercentage, + }, + "invalid-plugin-args": { + expectedToFail: true, + config: invalidPluginArgs, + }, + "duplicated-plugin-config": { + expectedToFail: true, + config: duplicatedPluginConfig, + }, + "mismatch-queue-sort": { + expectedToFail: true, + config: mismatchQueueSort, + }, + "bad-removed-plugins-1": { + expectedToFail: true, + config: badRemovedPlugins1, + }, + "bad-removed-plugins-3": { + expectedToFail: true, + config: badRemovedPlugins3, + }, + "good-removed-plugins-2": { + expectedToFail: false, + config: goodRemovedPlugins2, + }, + "bad-plugins-config": { + expectedToFail: true, + config: deprecatedPluginsConfig, + errorString: "profiles[0].pluginConfig[1]: Invalid value: \"NodeResourcesLeastAllocated\": was removed in version \"kubescheduler.config.k8s.io/v1beta2\" (KubeSchedulerConfiguration is version \"kubescheduler.config.k8s.io/v1beta2\")", + }, + } + + for name, scenario := range scenarios { + t.Run(name, func(t *testing.T) { + errs := ValidateKubeSchedulerConfiguration(scenario.config) + if errs == nil && scenario.expectedToFail { + t.Error("Unexpected success") + } + if errs != nil && !scenario.expectedToFail { + t.Errorf("Unexpected failure: %+v", errs) + } + fmt.Println(errs) + + if errs != nil && scenario.errorString != "" && errs.Error() != scenario.errorString { + t.Errorf("Unexpected error string\n want:\t%s\n got:\t%s", scenario.errorString, errs.Error()) + } + }) + } +} + +func TestValidateKubeSchedulerConfigurationV1beta3(t *testing.T) { + podInitialBackoffSeconds := int64(1) + podMaxBackoffSeconds := int64(1) + validConfig := &config.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta3.SchemeGroupVersion.String(), + }, + Parallelism: 8, + ClientConnection: componentbaseconfig.ClientConnectionConfiguration{ + AcceptContentTypes: "application/json", + ContentType: "application/json", + QPS: 10, + Burst: 10, + }, + LeaderElection: componentbaseconfig.LeaderElectionConfiguration{ + ResourceLock: "configmap", + LeaderElect: true, + LeaseDuration: metav1.Duration{Duration: 30 * time.Second}, + RenewDeadline: metav1.Duration{Duration: 15 * time.Second}, + RetryPeriod: metav1.Duration{Duration: 5 * time.Second}, + ResourceNamespace: "name", + ResourceName: "name", + }, + PodInitialBackoffSeconds: podInitialBackoffSeconds, + PodMaxBackoffSeconds: podMaxBackoffSeconds, + PercentageOfNodesToScore: 35, + Profiles: []config.KubeSchedulerProfile{ + { + SchedulerName: "me", + Plugins: &config.Plugins{ + QueueSort: config.PluginSet{ + Enabled: []config.Plugin{{Name: "CustomSort"}}, + }, + Score: config.PluginSet{ + Disabled: []config.Plugin{{Name: "*"}}, + }, + }, + PluginConfig: []config.PluginConfig{ + { + Name: "DefaultPreemption", + Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 10, MinCandidateNodesAbsolute: 100}, + }, + }, + }, + { + SchedulerName: "other", + Plugins: &config.Plugins{ + QueueSort: config.PluginSet{ + Enabled: []config.Plugin{{Name: "CustomSort"}}, + }, + Bind: config.PluginSet{ + Enabled: []config.Plugin{{Name: "CustomBind"}}, + }, + }, + }, + }, + Extenders: []config.Extender{ + { + PrioritizeVerb: "prioritize", + Weight: 1, + }, + }, + } + + invalidParallelismValue := validConfig.DeepCopy() + invalidParallelismValue.Parallelism = 0 + + resourceNameNotSet := validConfig.DeepCopy() + resourceNameNotSet.LeaderElection.ResourceName = "" + + resourceNamespaceNotSet := validConfig.DeepCopy() + resourceNamespaceNotSet.LeaderElection.ResourceNamespace = "" + + enableContentProfilingSetWithoutEnableProfiling := validConfig.DeepCopy() + enableContentProfilingSetWithoutEnableProfiling.EnableProfiling = false + enableContentProfilingSetWithoutEnableProfiling.EnableContentionProfiling = true + + metricsBindAddrInvalid := validConfig.DeepCopy() + metricsBindAddrInvalid.MetricsBindAddress = "0.0.0.0:9090" + + healthzBindAddrInvalid := validConfig.DeepCopy() + healthzBindAddrInvalid.HealthzBindAddress = "0.0.0.0:9090" + + percentageOfNodesToScore101 := validConfig.DeepCopy() + percentageOfNodesToScore101.PercentageOfNodesToScore = int32(101) + + schedulerNameNotSet := validConfig.DeepCopy() + schedulerNameNotSet.Profiles[1].SchedulerName = "" + + repeatedSchedulerName := validConfig.DeepCopy() + repeatedSchedulerName.Profiles[0].SchedulerName = "other" + + differentQueueSort := validConfig.DeepCopy() + differentQueueSort.Profiles[1].Plugins.QueueSort.Enabled[0].Name = "AnotherSort" + + oneEmptyQueueSort := validConfig.DeepCopy() + oneEmptyQueueSort.Profiles[0].Plugins = nil + + extenderNegativeWeight := validConfig.DeepCopy() + extenderNegativeWeight.Extenders[0].Weight = -1 + + invalidNodePercentage := validConfig.DeepCopy() + invalidNodePercentage.Profiles[0].PluginConfig = []config.PluginConfig{ + { + Name: "DefaultPreemption", + Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 200, MinCandidateNodesAbsolute: 100}, + }, + } + + invalidPluginArgs := validConfig.DeepCopy() + invalidPluginArgs.Profiles[0].PluginConfig = []config.PluginConfig{ + { + Name: "DefaultPreemption", + Args: &config.InterPodAffinityArgs{}, + }, + } + + duplicatedPluginConfig := validConfig.DeepCopy() + duplicatedPluginConfig.Profiles[0].PluginConfig = []config.PluginConfig{ + { + Name: "config", + }, + { + Name: "config", + }, + } + + mismatchQueueSort := validConfig.DeepCopy() + mismatchQueueSort.Profiles = []config.KubeSchedulerProfile{ + { + SchedulerName: "me", + Plugins: &config.Plugins{ + QueueSort: config.PluginSet{ + Enabled: []config.Plugin{{Name: "PrioritySort"}}, + }, + }, + PluginConfig: []config.PluginConfig{ + { + Name: "PrioritySort", + }, + }, + }, + { + SchedulerName: "other", + Plugins: &config.Plugins{ + QueueSort: config.PluginSet{ + Enabled: []config.Plugin{{Name: "CustomSort"}}, + }, + }, + PluginConfig: []config.PluginConfig{ + { + Name: "CustomSort", + }, + }, + }, + } + + extenderDuplicateManagedResource := validConfig.DeepCopy() + extenderDuplicateManagedResource.Extenders[0].ManagedResources = []config.ExtenderManagedResource{ + {Name: "foo", IgnoredByScheduler: false}, + {Name: "foo", IgnoredByScheduler: false}, + } + + extenderDuplicateBind := validConfig.DeepCopy() + extenderDuplicateBind.Extenders[0].BindVerb = "foo" + extenderDuplicateBind.Extenders = append(extenderDuplicateBind.Extenders, config.Extender{ + PrioritizeVerb: "prioritize", + BindVerb: "bar", + }) + + badRemovedPlugins1 := validConfig.DeepCopy() badRemovedPlugins1.Profiles[0].Plugins.Score.Enabled = append(badRemovedPlugins1.Profiles[0].Plugins.Score.Enabled, config.Plugin{Name: "ServiceAffinity", Weight: 2}) badRemovedPlugins2 := validConfig.DeepCopy() - badRemovedPlugins2.APIVersion = "kubescheduler.config.k8s.io/v1beta3" // hypothetical, v1beta3 doesn't exist badRemovedPlugins2.Profiles[0].Plugins.Score.Enabled = append(badRemovedPlugins2.Profiles[0].Plugins.Score.Enabled, config.Plugin{Name: "ServiceAffinity", Weight: 2}) - badRemovedPlugins3 := validConfig.DeepCopy() // default v1beta2 + badRemovedPlugins3 := validConfig.DeepCopy() badRemovedPlugins3.Profiles[0].Plugins.Score.Enabled = append(badRemovedPlugins3.Profiles[0].Plugins.Score.Enabled, config.Plugin{Name: "NodeResourcesMostAllocated", Weight: 2}) goodRemovedPlugins2 := validConfig.DeepCopy() @@ -313,7 +612,7 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) { "bad-plugins-config": { expectedToFail: true, config: deprecatedPluginsConfig, - errorString: "profiles[0].pluginConfig[1]: Invalid value: \"NodeResourcesLeastAllocated\": was removed in version \"kubescheduler.config.k8s.io/v1beta2\" (KubeSchedulerConfiguration is version \"kubescheduler.config.k8s.io/v1beta2\")", + errorString: "profiles[0].pluginConfig[1]: Invalid value: \"NodeResourcesLeastAllocated\": was removed in version \"kubescheduler.config.k8s.io/v1beta2\" (KubeSchedulerConfiguration is version \"kubescheduler.config.k8s.io/v1beta3\")", }, } diff --git a/pkg/scheduler/scheduler.go b/pkg/scheduler/scheduler.go index 4cf15c0f3a9fe..9ba951b86be77 100644 --- a/pkg/scheduler/scheduler.go +++ b/pkg/scheduler/scheduler.go @@ -38,7 +38,7 @@ import ( restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" "k8s.io/klog/v2" - "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kube-scheduler/config/v1beta3" podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/apis/core/validation" "k8s.io/kubernetes/pkg/scheduler/apis/config" @@ -231,7 +231,7 @@ func New(client clientset.Interface, } if options.applyDefaultProfile { - var versionedCfg v1beta2.KubeSchedulerConfiguration + var versionedCfg v1beta3.KubeSchedulerConfiguration scheme.Scheme.Default(&versionedCfg) cfg := config.KubeSchedulerConfiguration{} if err := scheme.Scheme.Convert(&versionedCfg, &cfg, nil); err != nil { From 1a484c1b9c311700b5ad0eaf189bfb76ccc8ef74 Mon Sep 17 00:00:00 2001 From: ravisantoshgudimetla Date: Mon, 9 Aug 2021 16:55:10 -0400 Subject: [PATCH 4/5] [scheduler][vendor]: add v1beta3 explicitly Vendor changes --- vendor/modules.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/modules.txt b/vendor/modules.txt index 5913ac4c62a16..e397ca3ff76a9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2078,6 +2078,7 @@ k8s.io/kube-proxy/config/v1alpha1 ## explicit k8s.io/kube-scheduler/config/v1 k8s.io/kube-scheduler/config/v1beta2 +k8s.io/kube-scheduler/config/v1beta3 k8s.io/kube-scheduler/extender/v1 # k8s.io/kubectl v0.0.0 => ./staging/src/k8s.io/kubectl ## explicit From 283b176102d239a98f5cb070040935f23e477888 Mon Sep 17 00:00:00 2001 From: ravisantoshgudimetla Date: Mon, 4 Oct 2021 13:55:00 -0400 Subject: [PATCH 5/5] [test]: modify integration tests to use v1beta3 --- test/integration/scheduler/framework_test.go | 176 +++++++++--------- test/integration/scheduler/preemption_test.go | 16 +- test/integration/scheduler/priorities_test.go | 14 +- test/integration/scheduler/queue_test.go | 12 +- test/integration/scheduler/scheduler_test.go | 22 +-- test/integration/scheduler/util.go | 12 +- 6 files changed, 126 insertions(+), 126 deletions(-) diff --git a/test/integration/scheduler/framework_test.go b/test/integration/scheduler/framework_test.go index 612e4b494c0f9..b819c783daf8f 100644 --- a/test/integration/scheduler/framework_test.go +++ b/test/integration/scheduler/framework_test.go @@ -33,7 +33,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" listersv1 "k8s.io/client-go/listers/core/v1" - "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kube-scheduler/config/v1beta3" "k8s.io/kubernetes/pkg/scheduler" schedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" configtesting "k8s.io/kubernetes/pkg/scheduler/apis/config/testing" @@ -540,12 +540,12 @@ func TestPreFilterPlugin(t *testing.T) { registry := frameworkruntime.Registry{prefilterPluginName: newPlugin(preFilterPlugin)} // Setup initial prefilter plugin for testing. - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - PreFilter: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + PreFilter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: prefilterPluginName}, }, }, @@ -685,32 +685,32 @@ func TestPostFilterPlugin(t *testing.T) { } // Setup plugins for testing. - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - Filter: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: filterPluginName}, }, }, - Score: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Score: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: scorePluginName}, }, // disable default in-tree Score plugins // to make it easy to control configured ScorePlugins failure - Disabled: []v1beta2.Plugin{ + Disabled: []v1beta3.Plugin{ {Name: "*"}, }, }, - PostFilter: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + PostFilter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: postfilterPluginName}, }, // Need to disable default in-tree PostFilter plugins, as they will // call RunFilterPlugins and hence impact the "numFilterCalled". - Disabled: []v1beta2.Plugin{ + Disabled: []v1beta3.Plugin{ {Name: "*"}, }, }, @@ -773,12 +773,12 @@ func TestScorePlugin(t *testing.T) { scorePluginName: newPlugin(scorePlugin), } - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - Score: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + Score: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: scorePluginName}, }, }, @@ -851,12 +851,12 @@ func TestNormalizeScorePlugin(t *testing.T) { } // Setup initial score plugin for testing. - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - Score: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + Score: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: scoreWithNormalizePluginName}, }, }, @@ -898,12 +898,12 @@ func TestReservePluginReserve(t *testing.T) { registry := frameworkruntime.Registry{reservePluginName: newPlugin(reservePlugin)} // Setup initial reserve plugin for testing. - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - Reserve: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + Reserve: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: reservePluginName}, }, }, @@ -975,13 +975,13 @@ func TestPrebindPlugin(t *testing.T) { // Setup initial prebind and filter plugin in different profiles. // The second profile ensures the embedded filter plugin is exclusively called, and hence // we can use its internal `numFilterCalled` to perform some precise checking logic. - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{ { SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - PreBind: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + PreBind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: preBindPluginName}, }, }, @@ -989,9 +989,9 @@ func TestPrebindPlugin(t *testing.T) { }, { SchedulerName: pointer.StringPtr("2nd-scheduler"), - Plugins: &v1beta2.Plugins{ - Filter: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: filterPluginName}, }, }, @@ -1255,20 +1255,20 @@ func TestBindPlugin(t *testing.T) { } // Setup initial unreserve and bind plugins for testing. - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - Reserve: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{{Name: reservePlugin.Name()}}, + Plugins: &v1beta3.Plugins{ + Reserve: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{{Name: reservePlugin.Name()}}, }, - Bind: v1beta2.PluginSet{ + Bind: v1beta3.PluginSet{ // Put DefaultBinder last. - Enabled: []v1beta2.Plugin{{Name: bindPlugin1.Name()}, {Name: bindPlugin2.Name()}, {Name: defaultbinder.Name}}, - Disabled: []v1beta2.Plugin{{Name: defaultbinder.Name}}, + Enabled: []v1beta3.Plugin{{Name: bindPlugin1.Name()}, {Name: bindPlugin2.Name()}, {Name: defaultbinder.Name}}, + Disabled: []v1beta3.Plugin{{Name: defaultbinder.Name}}, }, - PostBind: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{{Name: postBindPlugin.Name()}}, + PostBind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{{Name: postBindPlugin.Name()}}, }, }, }}, @@ -1444,19 +1444,19 @@ func TestPostBindPlugin(t *testing.T) { } // Setup initial prebind and postbind plugin for testing. - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - PreBind: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + PreBind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ { Name: preBindPluginName, }, }, }, - PostBind: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + PostBind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ { Name: postBindPluginName, }, @@ -1792,12 +1792,12 @@ func TestFilterPlugin(t *testing.T) { registry := frameworkruntime.Registry{filterPluginName: newPlugin(filterPlugin)} // Setup initial filter plugin for testing. - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - Filter: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: filterPluginName}, }, }, @@ -1864,12 +1864,12 @@ func TestPreScorePlugin(t *testing.T) { registry := frameworkruntime.Registry{preScorePluginName: newPlugin(preScorePlugin)} // Setup initial pre-score plugin for testing. - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - PreScore: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + PreScore: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: preScorePluginName}, }, }, @@ -1945,24 +1945,24 @@ func TestPreemptWithPermitPlugin(t *testing.T) { } // Setup initial permit and filter plugins in the profile. - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{ { SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - Permit: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + Permit: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: permitPluginName}, }, }, - Filter: v1beta2.PluginSet{ + Filter: v1beta3.PluginSet{ // Ensure the fake filter plugin is always called; otherwise noderesources // would fail first and exit the Filter phase. - Enabled: []v1beta2.Plugin{ + Enabled: []v1beta3.Plugin{ {Name: filterPluginName}, {Name: noderesources.FitName}, }, - Disabled: []v1beta2.Plugin{ + Disabled: []v1beta3.Plugin{ {Name: noderesources.FitName}, }, }, @@ -2194,17 +2194,17 @@ func TestActivatePods(t *testing.T) { }} // Setup initial filter plugin for testing. - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - PreFilter: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + PreFilter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: jobPluginName}, }, }, - PostBind: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + PostBind: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: jobPluginName}, }, }, @@ -2281,19 +2281,19 @@ func initRegistryAndConfig(t *testing.T, pp ...*PermitPlugin) (frameworkruntime. return frameworkruntime.Registry{}, schedulerconfig.KubeSchedulerProfile{} } - versionedCfg := v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + versionedCfg := v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - Permit: v1beta2.PluginSet{}, + Plugins: &v1beta3.Plugins{ + Permit: v1beta3.PluginSet{}, }, }}, } registry = frameworkruntime.Registry{} for _, p := range pp { registry.Register(p.Name(), newPermitPlugin(p)) - versionedCfg.Profiles[0].Plugins.Permit.Enabled = append(versionedCfg.Profiles[0].Plugins.Permit.Enabled, v1beta2.Plugin{Name: p.Name()}) + versionedCfg.Profiles[0].Plugins.Permit.Enabled = append(versionedCfg.Profiles[0].Plugins.Permit.Enabled, v1beta3.Plugin{Name: p.Name()}) } - cfg := configtesting.V1beta2ToInternalWithDefaults(t, versionedCfg) + cfg := configtesting.V1beta3ToInternalWithDefaults(t, versionedCfg) return registry, cfg.Profiles[0] } diff --git a/test/integration/scheduler/preemption_test.go b/test/integration/scheduler/preemption_test.go index f5e84f19ec866..69492ec91f632 100644 --- a/test/integration/scheduler/preemption_test.go +++ b/test/integration/scheduler/preemption_test.go @@ -40,7 +40,7 @@ import ( restclient "k8s.io/client-go/rest" featuregatetesting "k8s.io/component-base/featuregate/testing" "k8s.io/klog/v2" - "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kube-scheduler/config/v1beta3" podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/apis/scheduling" "k8s.io/kubernetes/pkg/features" @@ -134,17 +134,17 @@ func TestPreemption(t *testing.T) { if err != nil { t.Fatalf("Error registering a filter: %v", err) } - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - Filter: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: filterPluginName}, }, }, - PreFilter: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + PreFilter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: filterPluginName}, }, }, diff --git a/test/integration/scheduler/priorities_test.go b/test/integration/scheduler/priorities_test.go index 65f4c2e0930bf..cb93f5f698ae9 100644 --- a/test/integration/scheduler/priorities_test.go +++ b/test/integration/scheduler/priorities_test.go @@ -29,7 +29,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" utilfeature "k8s.io/apiserver/pkg/util/feature" featuregatetesting "k8s.io/component-base/featuregate/testing" - "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kube-scheduler/config/v1beta3" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/scheduler" configtesting "k8s.io/kubernetes/pkg/scheduler/apis/config/testing" @@ -45,15 +45,15 @@ import ( // This file tests the scheduler priority functions. func initTestSchedulerForPriorityTest(t *testing.T, scorePluginName string) *testutils.TestContext { - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - Score: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + Score: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: scorePluginName, Weight: pointer.Int32Ptr(1)}, }, - Disabled: []v1beta2.Plugin{ + Disabled: []v1beta3.Plugin{ {Name: "*"}, }, }, diff --git a/test/integration/scheduler/queue_test.go b/test/integration/scheduler/queue_test.go index 891d09fbb8d2f..68a515336cffd 100644 --- a/test/integration/scheduler/queue_test.go +++ b/test/integration/scheduler/queue_test.go @@ -34,7 +34,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" - "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kube-scheduler/config/v1beta3" apiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" "k8s.io/kubernetes/pkg/scheduler" configtesting "k8s.io/kubernetes/pkg/scheduler/apis/config/testing" @@ -126,12 +126,12 @@ func TestCustomResourceEnqueue(t *testing.T) { return &fakeCRPlugin{}, nil }, } - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - Filter: v1beta2.PluginSet{ - Enabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + Filter: v1beta3.PluginSet{ + Enabled: []v1beta3.Plugin{ {Name: "fakeCRPlugin"}, }, }, diff --git a/test/integration/scheduler/scheduler_test.go b/test/integration/scheduler/scheduler_test.go index 734e28c6dd471..d01ec2caea3e7 100644 --- a/test/integration/scheduler/scheduler_test.go +++ b/test/integration/scheduler/scheduler_test.go @@ -37,7 +37,7 @@ import ( restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/events" - "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kube-scheduler/config/v1beta3" "k8s.io/kubernetes/pkg/scheduler" "k8s.io/kubernetes/pkg/scheduler/apis/config" configtesting "k8s.io/kubernetes/pkg/scheduler/apis/config/testing" @@ -320,14 +320,14 @@ func TestSchedulerCreationFromNonExistentConfigMap(t *testing.T) { stopCh := make(chan struct{}) eventBroadcaster.StartRecordingToSink(stopCh) - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - PluginConfig: []v1beta2.PluginConfig{ + PluginConfig: []v1beta3.PluginConfig{ { Name: "VolumeBinding", Args: runtime.RawExtension{ - Object: &v1beta2.VolumeBindingArgs{ + Object: &v1beta3.VolumeBindingArgs{ BindTimeoutSeconds: pointer.Int64Ptr(30), }, }, @@ -558,14 +558,14 @@ func TestMultipleSchedulers(t *testing.T) { } // 5. create and start a scheduler with name "foo-scheduler" - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(fooScheduler), - PluginConfig: []v1beta2.PluginConfig{ + PluginConfig: []v1beta3.PluginConfig{ { Name: "VolumeBinding", Args: runtime.RawExtension{ - Object: &v1beta2.VolumeBindingArgs{ + Object: &v1beta3.VolumeBindingArgs{ BindTimeoutSeconds: pointer.Int64Ptr(30), }, }, @@ -634,8 +634,8 @@ func TestMultipleSchedulers(t *testing.T) { } func TestMultipleSchedulingProfiles(t *testing.T) { - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{ {SchedulerName: pointer.StringPtr("default-scheduler")}, {SchedulerName: pointer.StringPtr("custom-scheduler")}, }, diff --git a/test/integration/scheduler/util.go b/test/integration/scheduler/util.go index dc43ae1b2854a..f784bc51823d2 100644 --- a/test/integration/scheduler/util.go +++ b/test/integration/scheduler/util.go @@ -35,7 +35,7 @@ import ( restclient "k8s.io/client-go/rest" "k8s.io/client-go/restmapper" "k8s.io/client-go/scale" - "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kube-scheduler/config/v1beta3" podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/controller/disruption" "k8s.io/kubernetes/pkg/scheduler" @@ -93,12 +93,12 @@ func initTest(t *testing.T, nsPrefix string, opts ...scheduler.Option) *testutil // initTestDisablePreemption initializes a test environment and creates API server and scheduler with default // configuration but with pod preemption disabled. func initTestDisablePreemption(t *testing.T, nsPrefix string) *testutils.TestContext { - cfg := configtesting.V1beta2ToInternalWithDefaults(t, v1beta2.KubeSchedulerConfiguration{ - Profiles: []v1beta2.KubeSchedulerProfile{{ + cfg := configtesting.V1beta3ToInternalWithDefaults(t, v1beta3.KubeSchedulerConfiguration{ + Profiles: []v1beta3.KubeSchedulerProfile{{ SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName), - Plugins: &v1beta2.Plugins{ - PostFilter: v1beta2.PluginSet{ - Disabled: []v1beta2.Plugin{ + Plugins: &v1beta3.Plugins{ + PostFilter: v1beta3.PluginSet{ + Disabled: []v1beta3.Plugin{ {Name: defaultpreemption.Name}, }, },