diff --git a/cmd/kube-scheduler/app/options/configfile.go b/cmd/kube-scheduler/app/options/configfile.go index 032fb15bcc6..384e86fb480 100644 --- a/cmd/kube-scheduler/app/options/configfile.go +++ b/cmd/kube-scheduler/app/options/configfile.go @@ -17,18 +17,21 @@ limitations under the License. package options import ( + "bytes" "fmt" + "io" "io/ioutil" "os" "k8s.io/apimachinery/pkg/runtime" "k8s.io/klog/v2" - kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" - kubeschedulerscheme "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" - kubeschedulerconfigv1beta1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta1" + "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" + configv1beta1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta1" + configv1beta2 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta2" ) -func loadConfigFromFile(file string) (*kubeschedulerconfig.KubeSchedulerConfiguration, error) { +func loadConfigFromFile(file string) (*config.KubeSchedulerConfiguration, error) { data, err := ioutil.ReadFile(file) if err != nil { return nil, err @@ -37,39 +40,60 @@ func loadConfigFromFile(file string) (*kubeschedulerconfig.KubeSchedulerConfigur return loadConfig(data) } -func loadConfig(data []byte) (*kubeschedulerconfig.KubeSchedulerConfiguration, error) { +func loadConfig(data []byte) (*config.KubeSchedulerConfiguration, error) { // The UniversalDecoder runs defaulting and returns the internal type by default. - obj, gvk, err := kubeschedulerscheme.Codecs.UniversalDecoder().Decode(data, nil, nil) + obj, gvk, err := scheme.Codecs.UniversalDecoder().Decode(data, nil, nil) if err != nil { return nil, err } - if cfgObj, ok := obj.(*kubeschedulerconfig.KubeSchedulerConfiguration); ok { + if cfgObj, ok := obj.(*config.KubeSchedulerConfiguration); ok { + // We don't set this field in pkg/scheduler/apis/config/{version}/conversion.go + // because the field will be cleared later by API machinery during + // conversion. See KubeSchedulerConfiguration internal type definition for + // more details. + cfgObj.TypeMeta.APIVersion = gvk.GroupVersion().String() return cfgObj, nil } return nil, fmt.Errorf("couldn't decode as KubeSchedulerConfiguration, got %s: ", gvk) } +func encodeConfig(cfg *config.KubeSchedulerConfiguration) (*bytes.Buffer, error) { + buf := new(bytes.Buffer) + const mediaType = runtime.ContentTypeYAML + info, ok := runtime.SerializerInfoForMediaType(scheme.Codecs.SupportedMediaTypes(), mediaType) + if !ok { + return buf, fmt.Errorf("unable to locate encoder -- %q is not a supported media type", mediaType) + } + + var encoder runtime.Encoder + switch cfg.TypeMeta.APIVersion { + case configv1beta1.SchemeGroupVersion.String(): + encoder = scheme.Codecs.EncoderForVersion(info.Serializer, configv1beta1.SchemeGroupVersion) + case configv1beta2.SchemeGroupVersion.String(): + encoder = scheme.Codecs.EncoderForVersion(info.Serializer, configv1beta2.SchemeGroupVersion) + default: + encoder = scheme.Codecs.EncoderForVersion(info.Serializer, configv1beta2.SchemeGroupVersion) + } + if err := encoder.Encode(cfg, buf); err != nil { + return buf, err + } + return buf, nil +} + // LogOrWriteConfig logs the completed component config and writes it into the given file name as YAML, if either is enabled -func LogOrWriteConfig(fileName string, cfg *kubeschedulerconfig.KubeSchedulerConfiguration, completedProfiles []kubeschedulerconfig.KubeSchedulerProfile) error { +func LogOrWriteConfig(fileName string, cfg *config.KubeSchedulerConfiguration, completedProfiles []config.KubeSchedulerProfile) error { if !(klog.V(2).Enabled() || len(fileName) > 0) { return nil } cfg.Profiles = completedProfiles - const mediaType = runtime.ContentTypeYAML - info, ok := runtime.SerializerInfoForMediaType(kubeschedulerscheme.Codecs.SupportedMediaTypes(), mediaType) - if !ok { - return fmt.Errorf("unable to locate encoder -- %q is not a supported media type", mediaType) + buf, err := encodeConfig(cfg) + if err != nil { + return err } - encoder := kubeschedulerscheme.Codecs.EncoderForVersion(info.Serializer, kubeschedulerconfigv1beta1.SchemeGroupVersion) if klog.V(2).Enabled() { - bytes, err := runtime.Encode(encoder, cfg) - if err != nil { - return err - } - configString := string(bytes) - klog.InfoS("Using component config", "config", configString) + klog.InfoS("Using component config", "config", buf.String()) } if len(fileName) > 0 { @@ -78,7 +102,7 @@ func LogOrWriteConfig(fileName string, cfg *kubeschedulerconfig.KubeSchedulerCon return err } defer configFile.Close() - if err := encoder.Encode(cfg, configFile); err != nil { + if _, err := io.Copy(configFile, buf); err != nil { return err } klog.InfoS("Wrote configuration", "file", fileName) diff --git a/cmd/kube-scheduler/app/options/options.go b/cmd/kube-scheduler/app/options/options.go index bd2d88d9ff9..8d0e8b9904f 100644 --- a/cmd/kube-scheduler/app/options/options.go +++ b/cmd/kube-scheduler/app/options/options.go @@ -41,7 +41,7 @@ import ( configv1alpha1 "k8s.io/component-base/config/v1alpha1" "k8s.io/component-base/logs" "k8s.io/component-base/metrics" - kubeschedulerconfigv1beta1 "k8s.io/kube-scheduler/config/v1beta1" + configv1beta2 "k8s.io/kube-scheduler/config/v1beta2" schedulerappconfig "k8s.io/kubernetes/cmd/kube-scheduler/app/config" "k8s.io/kubernetes/pkg/scheduler" kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" @@ -133,7 +133,7 @@ func splitHostIntPort(s string) (string, int, error) { } func newDefaultComponentConfig() (*kubeschedulerconfig.KubeSchedulerConfiguration, error) { - versionedCfg := kubeschedulerconfigv1beta1.KubeSchedulerConfiguration{} + versionedCfg := configv1beta2.KubeSchedulerConfiguration{} versionedCfg.DebuggingConfiguration = *configv1alpha1.NewRecommendedDebuggingConfiguration() kubeschedulerscheme.Scheme.Default(&versionedCfg) @@ -141,6 +141,11 @@ func newDefaultComponentConfig() (*kubeschedulerconfig.KubeSchedulerConfiguratio if err := kubeschedulerscheme.Scheme.Convert(&versionedCfg, &cfg, nil); err != nil { return nil, err } + // We don't set this field in pkg/scheduler/apis/config/{version}/conversion.go + // because the field will be cleared later by API machinery during + // conversion. See KubeSchedulerConfiguration internal type definition for + // more details. + cfg.TypeMeta.APIVersion = configv1beta2.SchemeGroupVersion.String() return &cfg, nil } diff --git a/cmd/kube-scheduler/app/options/options_test.go b/cmd/kube-scheduler/app/options/options_test.go index e3a281af049..5894439d44b 100644 --- a/cmd/kube-scheduler/app/options/options_test.go +++ b/cmd/kube-scheduler/app/options/options_test.go @@ -34,11 +34,27 @@ import ( "k8s.io/apimachinery/pkg/runtime" apiserveroptions "k8s.io/apiserver/pkg/server/options" componentbaseconfig "k8s.io/component-base/config" + "k8s.io/component-base/config/v1alpha1" "k8s.io/component-base/logs" + "k8s.io/kube-scheduler/config/v1beta1" + "k8s.io/kube-scheduler/config/v1beta2" kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity" ) +func newV1beta1DefaultComponentConfig() (*kubeschedulerconfig.KubeSchedulerConfiguration, error) { + versionedCfg := v1beta1.KubeSchedulerConfiguration{} + versionedCfg.DebuggingConfiguration = *v1alpha1.NewRecommendedDebuggingConfiguration() + + scheme.Scheme.Default(&versionedCfg) + cfg := kubeschedulerconfig.KubeSchedulerConfiguration{} + if err := scheme.Scheme.Convert(&versionedCfg, &cfg, nil); err != nil { + return nil, err + } + return &cfg, nil +} + func TestSchedulerOptions(t *testing.T) { // temp dir tmpDir, err := ioutil.TempDir("", "scheduler-options") @@ -74,7 +90,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/v1beta1 +apiVersion: kubescheduler.config.k8s.io/v1beta2 kind: KubeSchedulerConfiguration clientConnection: kubeconfig: "%s" @@ -115,6 +131,17 @@ leaderElection: t.Fatal(err) } + v1beta1VersionConfig := filepath.Join(tmpDir, "scheduler_v1beta1_api_version.yaml") + if err := ioutil.WriteFile(v1beta1VersionConfig, []byte(fmt.Sprintf(` +apiVersion: kubescheduler.config.k8s.io/v1beta1 +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 @@ -138,7 +165,7 @@ leaderElection: unknownFieldConfig := filepath.Join(tmpDir, "scheduler_invalid_unknown_field.yaml") if err := ioutil.WriteFile(unknownFieldConfig, []byte(fmt.Sprintf(` -apiVersion: kubescheduler.config.k8s.io/v1beta1 +apiVersion: kubescheduler.config.k8s.io/v1beta2 kind: KubeSchedulerConfiguration clientConnection: kubeconfig: "%s" @@ -150,7 +177,7 @@ foo: bar`, configKubeconfig)), os.FileMode(0600)); err != nil { duplicateFieldConfig := filepath.Join(tmpDir, "scheduler_invalid_duplicate_fields.yaml") if err := ioutil.WriteFile(duplicateFieldConfig, []byte(fmt.Sprintf(` -apiVersion: kubescheduler.config.k8s.io/v1beta1 +apiVersion: kubescheduler.config.k8s.io/v1beta2 kind: KubeSchedulerConfiguration clientConnection: kubeconfig: "%s" @@ -187,7 +214,7 @@ users: // plugin config pluginConfigFile := filepath.Join(tmpDir, "plugin.yaml") if err := ioutil.WriteFile(pluginConfigFile, []byte(fmt.Sprintf(` -apiVersion: kubescheduler.config.k8s.io/v1beta1 +apiVersion: kubescheduler.config.k8s.io/v1beta2 kind: KubeSchedulerConfiguration clientConnection: kubeconfig: "%s" @@ -215,9 +242,65 @@ profiles: t.Fatal(err) } + // plugin config + v1beta1PluginConfigFile := filepath.Join(tmpDir, "v1beta1_plugin.yaml") + if err := ioutil.WriteFile(v1beta1PluginConfigFile, []byte(fmt.Sprintf(` +apiVersion: kubescheduler.config.k8s.io/v1beta1 +kind: KubeSchedulerConfiguration +clientConnection: + kubeconfig: "%s" +profiles: +- plugins: + reserve: + enabled: + - name: foo + - name: bar + disabled: + - name: baz + preBind: + enabled: + - name: foo + disabled: + - name: baz + pluginConfig: + - name: ServiceAffinity + args: + affinityLabels: [] + antiAffinityLabelsPreference: [] + - name: foo + args: + bar: baz +`, configKubeconfig)), os.FileMode(0600)); err != nil { + t.Fatal(err) + } + // multiple profiles config multiProfilesConfig := filepath.Join(tmpDir, "multi-profiles.yaml") if err := ioutil.WriteFile(multiProfilesConfig, []byte(fmt.Sprintf(` +apiVersion: kubescheduler.config.k8s.io/v1beta2 +kind: KubeSchedulerConfiguration +clientConnection: + kubeconfig: "%s" +profiles: +- schedulerName: "foo-profile" + plugins: + reserve: + enabled: + - name: foo +- schedulerName: "bar-profile" + plugins: + preBind: + disabled: + - name: baz + pluginConfig: + - name: foo +`, configKubeconfig)), os.FileMode(0600)); err != nil { + t.Fatal(err) + } + + // multiple profiles config + v1beta1MultiProfilesConfig := filepath.Join(tmpDir, "v1beta1_multi-profiles.yaml") + if err := ioutil.WriteFile(v1beta1MultiProfilesConfig, []byte(fmt.Sprintf(` apiVersion: kubescheduler.config.k8s.io/v1beta1 kind: KubeSchedulerConfiguration clientConnection: @@ -261,7 +344,7 @@ profiles: checkErrFn func(err error) bool }{ { - name: "config file", + name: "v1beta2 config file", options: &Options{ ConfigFile: configFile, ComponentConfig: func() kubeschedulerconfig.KubeSchedulerConfiguration { @@ -299,6 +382,82 @@ profiles: }, expectedUsername: "config", expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta2.SchemeGroupVersion.String(), + }, + Parallelism: 16, + AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, + HealthzBindAddress: "0.0.0.0:10251", + MetricsBindAddress: "0.0.0.0:10251", + 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"}, + }, + }, + }, + { + name: "v1beta1 config file", + options: &Options{ + ConfigFile: v1beta1VersionConfig, + ComponentConfig: func() kubeschedulerconfig.KubeSchedulerConfiguration { + cfg, err := newV1beta1DefaultComponentConfig() + if err != nil { + t.Fatal(err) + } + 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: v1beta1.SchemeGroupVersion.String(), + }, Parallelism: 16, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, HealthzBindAddress: "0.0.0.0:10251", @@ -345,7 +504,6 @@ profiles: }, expectedError: "no kind \"KubeSchedulerConfiguration\" is registered for version \"componentconfig/v1alpha1\"", }, - { name: "unknown version kubescheduler.config.k8s.io/unknown", options: &Options{ @@ -398,6 +556,9 @@ profiles: }, expectedUsername: "flag", expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta2.SchemeGroupVersion.String(), + }, Parallelism: 16, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, HealthzBindAddress: "", // defaults empty when not running from config file @@ -464,6 +625,9 @@ profiles: Logs: logs.NewOptions(), }, expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta2.SchemeGroupVersion.String(), + }, Parallelism: 16, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, HealthzBindAddress: "", // defaults empty when not running from config file @@ -504,6 +668,9 @@ profiles: }, expectedUsername: "config", expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta2.SchemeGroupVersion.String(), + }, Parallelism: 16, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, HealthzBindAddress: "0.0.0.0:10251", @@ -571,6 +738,85 @@ profiles: }, }, }, + { + name: "v1beta1 plugin config", + options: &Options{ + ConfigFile: v1beta1PluginConfigFile, + Logs: logs.NewOptions(), + }, + expectedUsername: "config", + expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta1.SchemeGroupVersion.String(), + }, + Parallelism: 16, + AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, + HealthzBindAddress: "0.0.0.0:10251", + MetricsBindAddress: "0.0.0.0:10251", + 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{ + Reserve: kubeschedulerconfig.PluginSet{ + Enabled: []kubeschedulerconfig.Plugin{ + {Name: "foo"}, + {Name: "bar"}, + }, + Disabled: []kubeschedulerconfig.Plugin{ + {Name: "baz"}, + }, + }, + PreBind: kubeschedulerconfig.PluginSet{ + Enabled: []kubeschedulerconfig.Plugin{ + {Name: "foo"}, + }, + Disabled: []kubeschedulerconfig.Plugin{ + {Name: "baz"}, + }, + }, + }, + PluginConfig: []kubeschedulerconfig.PluginConfig{ + { + Name: "ServiceAffinity", + Args: &kubeschedulerconfig.ServiceAffinityArgs{ + AffinityLabels: []string{}, + AntiAffinityLabelsPreference: []string{}, + }, + }, + { + Name: "foo", + Args: &runtime.Unknown{ + Raw: []byte(`{"bar":"baz"}`), + ContentType: "application/json", + }, + }, + }, + }, + }, + }, + }, { name: "multiple profiles", options: &Options{ @@ -579,6 +825,75 @@ profiles: }, expectedUsername: "config", expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta2.SchemeGroupVersion.String(), + }, + Parallelism: 16, + AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, + HealthzBindAddress: "0.0.0.0:10251", + MetricsBindAddress: "0.0.0.0:10251", + 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{ + Reserve: kubeschedulerconfig.PluginSet{ + Enabled: []kubeschedulerconfig.Plugin{ + {Name: "foo"}, + }, + }, + }, + }, + { + SchedulerName: "bar-profile", + Plugins: &kubeschedulerconfig.Plugins{ + PreBind: kubeschedulerconfig.PluginSet{ + Disabled: []kubeschedulerconfig.Plugin{ + {Name: "baz"}, + }, + }, + }, + PluginConfig: []kubeschedulerconfig.PluginConfig{ + { + Name: "foo", + }, + }, + }, + }, + }, + }, + { + name: "v1beta1 multiple profiles", + options: &Options{ + ConfigFile: v1beta1MultiProfilesConfig, + Logs: logs.NewOptions(), + }, + expectedUsername: "config", + expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta1.SchemeGroupVersion.String(), + }, Parallelism: 16, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, HealthzBindAddress: "0.0.0.0:10251", @@ -656,6 +971,9 @@ profiles: }, expectedUsername: "flag", expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta2.SchemeGroupVersion.String(), + }, Parallelism: 16, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ @@ -709,6 +1027,9 @@ profiles: }, expectedUsername: "flag", expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta2.SchemeGroupVersion.String(), + }, Parallelism: 16, AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource}, DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{ @@ -798,6 +1119,10 @@ profiles: return } + if _, err := encodeConfig(&config.ComponentConfig); err != nil { + t.Errorf("unexpected error in encodeConfig: %v", err) + } + if diff := cmp.Diff(tc.expectedConfig, config.ComponentConfig); diff != "" { t.Errorf("incorrect config (-want,+got):\n%s", diff) } diff --git a/cmd/kube-scheduler/app/server.go b/cmd/kube-scheduler/app/server.go index 1593f564624..4ce283dea1b 100644 --- a/cmd/kube-scheduler/app/server.go +++ b/cmd/kube-scheduler/app/server.go @@ -330,6 +330,7 @@ func Setup(ctx context.Context, opts *options.Options, outOfTreeRegistryOptions cc.InformerFactory, recorderFactory, ctx.Done(), + scheduler.WithComponentConfigVersion(cc.ComponentConfig.TypeMeta.APIVersion), scheduler.WithKubeConfig(cc.KubeConfig), scheduler.WithProfiles(cc.ComponentConfig.Profiles...), scheduler.WithAlgorithmSource(cc.ComponentConfig.AlgorithmSource), diff --git a/hack/.import-aliases b/hack/.import-aliases index 600d65d241c..a96af5f6aa8 100644 --- a/hack/.import-aliases +++ b/hack/.import-aliases @@ -52,6 +52,7 @@ "k8s.io/kubernetes/pkg/kubelet/apis/resourcemetrics/v1alpha1": "kubeletresourcemetricsv1alpha1", "k8s.io/kubernetes/pkg/proxy/apis/config/v1alpha1": "proxyconfigv1alpha1", "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta1": "schedulerconfigv1beta1", + "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta2": "schedulerconfigv1beta2", "k8s.io/kubernetes/test/e2e/framework/auth": "e2eauth", "k8s.io/kubernetes/test/e2e/framework/autoscaling": "e2eautoscaling", "k8s.io/kubernetes/test/e2e/framework/config": "e2econfig", diff --git a/pkg/scheduler/apis/config/scheme/scheme.go b/pkg/scheduler/apis/config/scheme/scheme.go index f50a1a33d8f..0b30657395e 100644 --- a/pkg/scheduler/apis/config/scheme/scheme.go +++ b/pkg/scheduler/apis/config/scheme/scheme.go @@ -20,9 +20,10 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" - kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" - kubeschedulerconfigv1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1" - kubeschedulerconfigv1beta1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta1" + config "k8s.io/kubernetes/pkg/scheduler/apis/config" + configv1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1" + configv1beta1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta1" + configv1beta2 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta2" ) var ( @@ -39,8 +40,9 @@ func init() { // AddToScheme builds the kubescheduler scheme using all known versions of the kubescheduler api. func AddToScheme(scheme *runtime.Scheme) { - utilruntime.Must(kubeschedulerconfig.AddToScheme(scheme)) - utilruntime.Must(kubeschedulerconfigv1.AddToScheme(scheme)) - utilruntime.Must(kubeschedulerconfigv1beta1.AddToScheme(scheme)) - utilruntime.Must(scheme.SetVersionPriority(kubeschedulerconfigv1beta1.SchemeGroupVersion)) + utilruntime.Must(config.AddToScheme(scheme)) + utilruntime.Must(configv1.AddToScheme(scheme)) + utilruntime.Must(configv1beta1.AddToScheme(scheme)) + utilruntime.Must(configv1beta2.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(configv1beta2.SchemeGroupVersion, configv1beta1.SchemeGroupVersion)) } diff --git a/pkg/scheduler/apis/config/scheme/scheme_test.go b/pkg/scheduler/apis/config/scheme/scheme_test.go index 2fa682c763a..ce3fb13c3aa 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/v1beta1" + "k8s.io/kube-scheduler/config/v1beta2" "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/utils/pointer" "sigs.k8s.io/yaml" @@ -39,6 +40,7 @@ func TestCodecsDecodePluginConfig(t *testing.T) { wantErr string wantProfiles []config.KubeSchedulerProfile }{ + //v1beta1 tests { name: "v1beta1 all plugin args in default profile", data: []byte(` @@ -285,6 +287,305 @@ profiles: apiVersion: kubescheduler.config.k8s.io/v1beta1 kind: KubeSchedulerConfiguration profiles: +- pluginConfig: + - name: DefaultPreemption + args: + - name: InterPodAffinity + args: + - name: NodeResourcesFit + - name: OutOfTreePlugin + args: + - name: NodeResourcesLeastAllocated + args: + - name: NodeResourcesMostAllocated + args: + - name: VolumeBinding + args: + - name: PodTopologySpread + - name: NodeAffinity +`), + wantProfiles: []config.KubeSchedulerProfile{ + { + SchedulerName: "default-scheduler", + PluginConfig: []config.PluginConfig{ + { + Name: "DefaultPreemption", + Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 10, MinCandidateNodesAbsolute: 100}, + }, + { + Name: "InterPodAffinity", + Args: &config.InterPodAffinityArgs{ + HardPodAffinityWeight: 1, + }, + }, + { + Name: "NodeResourcesFit", + Args: &config.NodeResourcesFitArgs{}, + }, + {Name: "OutOfTreePlugin"}, + { + Name: "NodeResourcesLeastAllocated", + Args: &config.NodeResourcesLeastAllocatedArgs{ + Resources: []config.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }, + }, + { + Name: "NodeResourcesMostAllocated", + Args: &config.NodeResourcesMostAllocatedArgs{ + Resources: []config.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, + }, + }, + { + Name: "VolumeBinding", + Args: &config.VolumeBindingArgs{ + BindTimeoutSeconds: 600, + }, + }, + { + Name: "PodTopologySpread", + Args: &config.PodTopologySpreadArgs{ + DefaultingType: config.SystemDefaulting, + }, + }, + { + Name: "NodeAffinity", + Args: &config.NodeAffinityArgs{}, + }, + }, + }, + }, + }, + // v1beta2 tests + { + name: "v1beta2 all plugin args in default profile", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta2 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: DefaultPreemption + args: + minCandidateNodesPercentage: 50 + minCandidateNodesAbsolute: 500 + - name: InterPodAffinity + args: + hardPodAffinityWeight: 5 + - name: NodeResourcesFit + args: + ignoredResources: ["foo"] + - name: RequestedToCapacityRatio + args: + shape: + - utilization: 1 + - name: PodTopologySpread + args: + defaultConstraints: + - maxSkew: 1 + topologyKey: zone + whenUnsatisfiable: ScheduleAnyway + - name: NodeResourcesLeastAllocated + args: + resources: + - name: cpu + weight: 2 + - name: unknown + weight: 1 + - name: NodeResourcesMostAllocated + args: + resources: + - name: memory + weight: 1 + - name: VolumeBinding + args: + bindTimeoutSeconds: 300 + - name: NodeAffinity + args: + addedAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: foo + operator: In + values: ["bar"] +`), + wantProfiles: []config.KubeSchedulerProfile{ + { + SchedulerName: "default-scheduler", + 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"}}, + }, + { + Name: "RequestedToCapacityRatio", + Args: &config.RequestedToCapacityRatioArgs{ + Shape: []config.UtilizationShapePoint{{Utilization: 1}}, + 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: "NodeResourcesLeastAllocated", + Args: &config.NodeResourcesLeastAllocatedArgs{ + Resources: []config.ResourceSpec{{Name: "cpu", Weight: 2}, {Name: "unknown", Weight: 1}}, + }, + }, + { + Name: "NodeResourcesMostAllocated", + Args: &config.NodeResourcesMostAllocatedArgs{ + Resources: []config.ResourceSpec{{Name: "memory", Weight: 1}}, + }, + }, + { + 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: "v1beta2 plugins can include version and kind", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta2 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: DefaultPreemption + args: + apiVersion: kubescheduler.config.k8s.io/v1beta2 + kind: DefaultPreemptionArgs + minCandidateNodesPercentage: 50 +`), + wantProfiles: []config.KubeSchedulerProfile{ + { + SchedulerName: "default-scheduler", + PluginConfig: []config.PluginConfig{ + { + Name: "DefaultPreemption", + Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 50, MinCandidateNodesAbsolute: 100}, + }, + }, + }, + }, + }, + { + name: "plugin group and kind should match the type", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta2 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: DefaultPreemption + args: + apiVersion: kubescheduler.config.k8s.io/v1beta2 + 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: "v1beta2 RequestedToCapacityRatioArgs shape encoding is strict", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta2 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: RequestedToCapacityRatio + args: + shape: + - Utilization: 1 + Score: 2 +`), + wantErr: `decoding .profiles[0].pluginConfig[0]: decoding args for plugin RequestedToCapacityRatio: strict decoder error for {"shape":[{"Score":2,"Utilization":1}]}: v1beta2.RequestedToCapacityRatioArgs.Shape: []v1beta2.UtilizationShapePoint: v1beta2.UtilizationShapePoint.ReadObject: found unknown field: Score, error found in #10 byte of ...|:[{"Score":2,"Utiliz|..., bigger context ...|{"shape":[{"Score":2,"Utilization":1}]}|...`, + }, + { + name: "v1beta2 RequestedToCapacityRatioArgs resources encoding is strict", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta2 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: RequestedToCapacityRatio + args: + shape: + - utilization: 1 + score: 2 + resources: + - Name: 1 + Weight: 2 +`), + wantErr: `decoding .profiles[0].pluginConfig[0]: decoding args for plugin RequestedToCapacityRatio: strict decoder error for {"resources":[{"Name":1,"Weight":2}],"shape":[{"score":2,"utilization":1}]}: v1beta2.RequestedToCapacityRatioArgs.Shape: []v1beta2.UtilizationShapePoint: Resources: []v1beta2.ResourceSpec: v1beta2.ResourceSpec.ReadObject: found unknown field: Name, error found in #10 byte of ...|":[{"Name":1,"Weight|..., bigger context ...|{"resources":[{"Name":1,"Weight":2}],"shape":[{"score":2,"utilization":|...`, + }, + { + name: "out-of-tree plugin args", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta2 +kind: KubeSchedulerConfiguration +profiles: +- pluginConfig: + - name: OutOfTreePlugin + args: + foo: bar +`), + wantProfiles: []config.KubeSchedulerProfile{ + { + SchedulerName: "default-scheduler", + PluginConfig: []config.PluginConfig{ + { + Name: "OutOfTreePlugin", + Args: &runtime.Unknown{ + ContentType: "application/json", + Raw: []byte(`{"foo":"bar"}`), + }, + }, + }, + }, + }, + }, + { + name: "empty and no plugin args", + data: []byte(` +apiVersion: kubescheduler.config.k8s.io/v1beta2 +kind: KubeSchedulerConfiguration +profiles: - pluginConfig: - name: DefaultPreemption args: @@ -385,6 +686,7 @@ func TestCodecsEncodePluginConfig(t *testing.T) { version schema.GroupVersion want string }{ + //v1beta1 tests { name: "v1beta1 in-tree and out-of-tree plugins", version: v1beta1.SchemeGroupVersion, @@ -594,6 +896,218 @@ profiles: foo: bar name: OutOfTreePlugin schedulerName: "" +`, + }, + //v1beta2 tests + { + name: "v1beta2 in-tree and out-of-tree plugins", + version: v1beta2.SchemeGroupVersion, + obj: &v1beta2.KubeSchedulerConfiguration{ + Profiles: []v1beta2.KubeSchedulerProfile{ + { + PluginConfig: []v1beta2.PluginConfig{ + { + Name: "InterPodAffinity", + Args: runtime.RawExtension{ + Object: &v1beta2.InterPodAffinityArgs{ + HardPodAffinityWeight: pointer.Int32Ptr(5), + }, + }, + }, + { + Name: "VolumeBinding", + Args: runtime.RawExtension{ + Object: &v1beta2.VolumeBindingArgs{ + BindTimeoutSeconds: pointer.Int64Ptr(300), + }, + }, + }, + { + Name: "RequestedToCapacityRatio", + Args: runtime.RawExtension{ + Object: &v1beta2.RequestedToCapacityRatioArgs{ + Shape: []v1beta2.UtilizationShapePoint{ + {Utilization: 1, Score: 2}, + }, + Resources: []v1beta2.ResourceSpec{ + {Name: "cpu", Weight: 2}, + }, + }, + }, + }, + { + Name: "NodeResourcesLeastAllocated", + Args: runtime.RawExtension{ + Object: &v1beta2.NodeResourcesLeastAllocatedArgs{ + Resources: []v1beta2.ResourceSpec{ + {Name: "mem", Weight: 2}, + }, + }, + }, + }, + { + Name: "PodTopologySpread", + Args: runtime.RawExtension{ + Object: &v1beta2.PodTopologySpreadArgs{ + DefaultConstraints: []corev1.TopologySpreadConstraint{}, + }, + }, + }, + { + Name: "OutOfTreePlugin", + Args: runtime.RawExtension{ + Raw: []byte(`{"foo":"bar"}`), + }, + }, + }, + }, + }, + }, + want: `apiVersion: kubescheduler.config.k8s.io/v1beta2 +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/v1beta2 + hardPodAffinityWeight: 5 + kind: InterPodAffinityArgs + name: InterPodAffinity + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta2 + bindTimeoutSeconds: 300 + kind: VolumeBindingArgs + name: VolumeBinding + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta2 + kind: RequestedToCapacityRatioArgs + resources: + - name: cpu + weight: 2 + shape: + - score: 2 + utilization: 1 + name: RequestedToCapacityRatio + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta2 + kind: NodeResourcesLeastAllocatedArgs + resources: + - name: mem + weight: 2 + name: NodeResourcesLeastAllocated + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta2 + kind: PodTopologySpreadArgs + name: PodTopologySpread + - args: + foo: bar + name: OutOfTreePlugin +`, + }, + { + name: "v1beta2 in-tree and out-of-tree plugins from internal", + version: v1beta2.SchemeGroupVersion, + obj: &config.KubeSchedulerConfiguration{ + Parallelism: 8, + Profiles: []config.KubeSchedulerProfile{ + { + PluginConfig: []config.PluginConfig{ + { + Name: "InterPodAffinity", + Args: &config.InterPodAffinityArgs{ + HardPodAffinityWeight: 5, + }, + }, + { + Name: "NodeResourcesMostAllocated", + Args: &config.NodeResourcesMostAllocatedArgs{ + 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/v1beta2 +clientConnection: + acceptContentTypes: "" + burst: 0 + contentType: "" + kubeconfig: "" + qps: 0 +enableContentionProfiling: false +enableProfiling: false +healthzBindAddress: "" +kind: KubeSchedulerConfiguration +leaderElection: + leaderElect: false + leaseDuration: 0s + renewDeadline: 0s + resourceLock: "" + resourceName: "" + resourceNamespace: "" + retryPeriod: 0s +metricsBindAddress: "" +parallelism: 8 +percentageOfNodesToScore: 0 +podInitialBackoffSeconds: 0 +podMaxBackoffSeconds: 0 +profiles: +- pluginConfig: + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta2 + hardPodAffinityWeight: 5 + kind: InterPodAffinityArgs + name: InterPodAffinity + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta2 + kind: NodeResourcesMostAllocatedArgs + resources: + - name: cpu + weight: 1 + name: NodeResourcesMostAllocated + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta2 + bindTimeoutSeconds: 300 + kind: VolumeBindingArgs + name: VolumeBinding + - args: + apiVersion: kubescheduler.config.k8s.io/v1beta2 + kind: PodTopologySpreadArgs + name: PodTopologySpread + - args: + foo: bar + name: OutOfTreePlugin + schedulerName: "" `, }, } diff --git a/pkg/scheduler/apis/config/types.go b/pkg/scheduler/apis/config/types.go index 531f20d153c..9dec5b48d99 100644 --- a/pkg/scheduler/apis/config/types.go +++ b/pkg/scheduler/apis/config/types.go @@ -47,6 +47,14 @@ const ( // KubeSchedulerConfiguration configures a scheduler type KubeSchedulerConfiguration struct { + // TypeMeta contains the API version and kind. In kube-scheduler, after + // conversion from the versioned KubeSchedulerConfiguration type to this + // internal type, we set the APIVersion field to the scheme group/version of + // the type we converted from. This is done in cmd/kube-scheduler in two + // places: (1) when loading config from a file, (2) generating the default + // config. Based on the versioned type set in this field, we make decisions; + // for example (1) during validation to check for usage of removed plugins, + // (2) writing config to a file, (3) initialising the scheduler. metav1.TypeMeta // Parallelism defines the amount of parallelism in algorithms for scheduling a Pods. Must be greater than 0. Defaults to 16 diff --git a/pkg/scheduler/apis/config/types_pluginargs.go b/pkg/scheduler/apis/config/types_pluginargs.go index 30e9542edd9..cdcdb02cac3 100644 --- a/pkg/scheduler/apis/config/types_pluginargs.go +++ b/pkg/scheduler/apis/config/types_pluginargs.go @@ -57,6 +57,10 @@ type InterPodAffinityArgs struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // NodeLabelArgs holds arguments used to configure the NodeLabel plugin. +// +// This plugin has been deprecated and is only configurable through the +// scheduler policy API and the v1beta1 component config API. It is recommended +// to use the NodeAffinity plugin instead. type NodeLabelArgs struct { metav1.TypeMeta @@ -180,7 +184,12 @@ type ResourceSpec struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// ServiceAffinityArgs holds arguments used to configure the ServiceAffinity plugin. +// ServiceAffinityArgs holds arguments used to configure the ServiceAffinity +// plugin. +// +// This plugin has been deprecated and is only configurable through the +// scheduler policy API and the v1beta1 component config API. It is recommended +// to use the InterPodAffinity plugin instead. type ServiceAffinityArgs struct { metav1.TypeMeta diff --git a/pkg/scheduler/apis/config/v1beta1/conversion_test.go b/pkg/scheduler/apis/config/v1beta1/conversion_test.go index 75ac0e93dec..6872f282a38 100644 --- a/pkg/scheduler/apis/config/v1beta1/conversion_test.go +++ b/pkg/scheduler/apis/config/v1beta1/conversion_test.go @@ -35,7 +35,11 @@ func TestV1beta1ToConfigKubeSchedulerConfigurationConversion(t *testing.T) { { name: "default conversion v1beta1 to config", config: v1beta1.KubeSchedulerConfiguration{}, - want: config.KubeSchedulerConfiguration{AlgorithmSource: config.SchedulerAlgorithmSource{Provider: pointer.StringPtr(v1beta1.SchedulerDefaultProviderName)}}, + want: config.KubeSchedulerConfiguration{ + AlgorithmSource: config.SchedulerAlgorithmSource{ + Provider: pointer.StringPtr(v1beta1.SchedulerDefaultProviderName), + }, + }, }, } diff --git a/pkg/scheduler/apis/config/v1beta1/defaults.go b/pkg/scheduler/apis/config/v1beta1/defaults.go index dd2a436b037..3b039bf7235 100644 --- a/pkg/scheduler/apis/config/v1beta1/defaults.go +++ b/pkg/scheduler/apis/config/v1beta1/defaults.go @@ -208,7 +208,6 @@ func SetDefaults_VolumeBindingArgs(obj *v1beta1.VolumeBindingArgs) { func SetDefaults_PodTopologySpreadArgs(obj *v1beta1.PodTopologySpreadArgs) { if feature.DefaultFeatureGate.Enabled(features.DefaultPodTopologySpread) { if obj.DefaultingType == "" { - // TODO(#94008): Always default to System in v1beta2. if len(obj.DefaultConstraints) != 0 { obj.DefaultingType = v1beta1.ListDefaulting } else { diff --git a/pkg/scheduler/apis/config/v1beta2/conversion.go b/pkg/scheduler/apis/config/v1beta2/conversion.go new file mode 100644 index 00000000000..b9e533d6293 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta2/conversion.go @@ -0,0 +1,109 @@ +/* +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 v1beta2 + +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/v1beta2" + "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/utils/pointer" +) + +var ( + // pluginArgConversionScheme is a scheme with internal and v1beta2 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_v1beta2_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(in *v1beta2.KubeSchedulerConfiguration, out *config.KubeSchedulerConfiguration, s conversion.Scope) error { + if err := autoConvert_v1beta2_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(in, out, s); err != nil { + return err + } + out.AlgorithmSource.Provider = pointer.StringPtr(v1beta2.SchedulerDefaultProviderName) + 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 { + for j := range out.Profiles[i].PluginConfig { + args := out.Profiles[i].PluginConfig[j].Args + if args == nil { + continue + } + if _, isUnknown := args.(*runtime.Unknown); isUnknown { + continue + } + scheme.Default(args) + 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) + } + out.Profiles[i].PluginConfig[j].Args = internalArgs + } + } + return nil +} + +func Convert_config_KubeSchedulerConfiguration_To_v1beta2_KubeSchedulerConfiguration(in *config.KubeSchedulerConfiguration, out *v1beta2.KubeSchedulerConfiguration, s conversion.Scope) error { + if err := autoConvert_config_KubeSchedulerConfiguration_To_v1beta2_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 *v1beta2.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/v1beta2/conversion_test.go b/pkg/scheduler/apis/config/v1beta2/conversion_test.go new file mode 100644 index 00000000000..6c5589cbb21 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta2/conversion_test.go @@ -0,0 +1,62 @@ +/* +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 v1beta2 + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/utils/pointer" +) + +func TestV1beta2ToConfigKubeSchedulerConfigurationConversion(t *testing.T) { + cases := []struct { + name string + config v1beta2.KubeSchedulerConfiguration + want config.KubeSchedulerConfiguration + }{ + { + name: "default conversion v1beta2 to config", + config: v1beta2.KubeSchedulerConfiguration{}, + want: config.KubeSchedulerConfiguration{ + AlgorithmSource: config.SchedulerAlgorithmSource{ + Provider: pointer.StringPtr(v1beta2.SchedulerDefaultProviderName), + }, + }, + }, + } + + scheme := runtime.NewScheme() + if err := AddToScheme(scheme); err != nil { + t.Fatal(err) + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + var got config.KubeSchedulerConfiguration + if err := scheme.Convert(&tc.config, &got, nil); err != nil { + t.Errorf("failed to convert: %+v", err) + } + if diff := cmp.Diff(tc.want, got); diff != "" { + t.Errorf("unexpected conversion (-want, +got):\n%s", diff) + } + }) + } +} diff --git a/pkg/scheduler/apis/config/v1beta2/defaults.go b/pkg/scheduler/apis/config/v1beta2/defaults.go new file mode 100644 index 00000000000..02d64901de2 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta2/defaults.go @@ -0,0 +1,213 @@ +/* +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 v1beta2 + +import ( + "net" + "strconv" + + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/util/feature" + componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1" + "k8s.io/kube-scheduler/config/v1beta2" + "k8s.io/kubernetes/pkg/features" + "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/utils/pointer" +) + +var defaultResourceSpec = []v1beta2.ResourceSpec{ + {Name: string(corev1.ResourceCPU), Weight: 1}, + {Name: string(corev1.ResourceMemory), Weight: 1}, +} + +func addDefaultingFuncs(scheme *runtime.Scheme) error { + return RegisterDefaults(scheme) +} + +// SetDefaults_KubeSchedulerConfiguration sets additional defaults +func SetDefaults_KubeSchedulerConfiguration(obj *v1beta2.KubeSchedulerConfiguration) { + + if obj.Parallelism == nil { + obj.Parallelism = pointer.Int32Ptr(16) + } + + if len(obj.Profiles) == 0 { + obj.Profiles = append(obj.Profiles, v1beta2.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) + } + + // For Healthz and Metrics bind addresses, we want to check: + // 1. If the value is nil, default to 0.0.0.0 and default scheduler port + // 2. If there is a value set, attempt to split it. If it's just a port (ie, ":1234"), default to 0.0.0.0 with that port + // 3. If splitting the value fails, check if the value is even a valid IP. If so, use that with the default port. + // Otherwise leave the address as-is, it will be caught during validation. + defaultBindAddress := net.JoinHostPort("0.0.0.0", strconv.Itoa(config.DefaultInsecureSchedulerPort)) + if obj.HealthzBindAddress == nil { + obj.HealthzBindAddress = &defaultBindAddress + } else { + if host, port, err := net.SplitHostPort(*obj.HealthzBindAddress); err == nil { + if len(host) == 0 { + host = "0.0.0.0" + } + hostPort := net.JoinHostPort(host, port) + obj.HealthzBindAddress = &hostPort + } else { + // Something went wrong splitting the host/port, could just be a missing port so check if the + // existing value is a valid IP address. If so, use that with the default scheduler port + if host := net.ParseIP(*obj.HealthzBindAddress); host != nil { + hostPort := net.JoinHostPort(*obj.HealthzBindAddress, strconv.Itoa(config.DefaultInsecureSchedulerPort)) + obj.HealthzBindAddress = &hostPort + } + } + } + + if obj.MetricsBindAddress == nil { + obj.MetricsBindAddress = &defaultBindAddress + } else { + if host, port, err := net.SplitHostPort(*obj.MetricsBindAddress); err == nil { + if len(host) == 0 { + host = "0.0.0.0" + } + hostPort := net.JoinHostPort(host, port) + obj.MetricsBindAddress = &hostPort + } else { + // Something went wrong splitting the host/port, could just be a missing port so check if the + // existing value is a valid IP address. If so, use that with the default scheduler port + if host := net.ParseIP(*obj.MetricsBindAddress); host != nil { + hostPort := net.JoinHostPort(*obj.MetricsBindAddress, strconv.Itoa(config.DefaultInsecureSchedulerPort)) + obj.MetricsBindAddress = &hostPort + } + } + } + + 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 = v1beta2.SchedulerDefaultLockObjectNamespace + } + if len(obj.LeaderElection.ResourceName) == 0 { + obj.LeaderElection.ResourceName = v1beta2.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 *v1beta2.DefaultPreemptionArgs) { + if obj.MinCandidateNodesPercentage == nil { + obj.MinCandidateNodesPercentage = pointer.Int32Ptr(10) + } + if obj.MinCandidateNodesAbsolute == nil { + obj.MinCandidateNodesAbsolute = pointer.Int32Ptr(100) + } +} + +func SetDefaults_InterPodAffinityArgs(obj *v1beta2.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_NodeResourcesLeastAllocatedArgs(obj *v1beta2.NodeResourcesLeastAllocatedArgs) { + if len(obj.Resources) == 0 { + // If no resources specified, used the default set. + obj.Resources = append(obj.Resources, defaultResourceSpec...) + } +} + +func SetDefaults_NodeResourcesMostAllocatedArgs(obj *v1beta2.NodeResourcesMostAllocatedArgs) { + if len(obj.Resources) == 0 { + // If no resources specified, used the default set. + obj.Resources = append(obj.Resources, defaultResourceSpec...) + } +} + +func SetDefaults_RequestedToCapacityRatioArgs(obj *v1beta2.RequestedToCapacityRatioArgs) { + if len(obj.Resources) == 0 { + // If no resources specified, used the default set. + obj.Resources = append(obj.Resources, defaultResourceSpec...) + } +} + +func SetDefaults_VolumeBindingArgs(obj *v1beta2.VolumeBindingArgs) { + if obj.BindTimeoutSeconds == nil { + obj.BindTimeoutSeconds = pointer.Int64Ptr(600) + } +} + +func SetDefaults_PodTopologySpreadArgs(obj *v1beta2.PodTopologySpreadArgs) { + if feature.DefaultFeatureGate.Enabled(features.DefaultPodTopologySpread) { + if obj.DefaultingType == "" { + obj.DefaultingType = v1beta2.SystemDefaulting + } + return + } + if obj.DefaultingType == "" { + obj.DefaultingType = v1beta2.ListDefaulting + } +} diff --git a/pkg/scheduler/apis/config/v1beta2/defaults_test.go b/pkg/scheduler/apis/config/v1beta2/defaults_test.go new file mode 100644 index 00000000000..4aaebd0dda5 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta2/defaults_test.go @@ -0,0 +1,516 @@ +/* +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 v1beta2 + +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/v1beta2" + "k8s.io/kubernetes/pkg/features" + "k8s.io/utils/pointer" +) + +func TestSchedulerDefaults(t *testing.T) { + enable := true + tests := []struct { + name string + config *v1beta2.KubeSchedulerConfiguration + expected *v1beta2.KubeSchedulerConfiguration + }{ + { + name: "empty config", + config: &v1beta2.KubeSchedulerConfiguration{}, + expected: &v1beta2.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + HealthzBindAddress: pointer.StringPtr("0.0.0.0:10251"), + MetricsBindAddress: pointer.StringPtr("0.0.0.0:10251"), + 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: []v1beta2.KubeSchedulerProfile{ + {SchedulerName: pointer.StringPtr("default-scheduler")}, + }, + }, + }, + { + name: "no scheduler name", + config: &v1beta2.KubeSchedulerConfiguration{ + Profiles: []v1beta2.KubeSchedulerProfile{ + { + PluginConfig: []v1beta2.PluginConfig{ + {Name: "FooPlugin"}, + }, + }, + }, + }, + expected: &v1beta2.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + HealthzBindAddress: pointer.StringPtr("0.0.0.0:10251"), + MetricsBindAddress: pointer.StringPtr("0.0.0.0:10251"), + 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: []v1beta2.KubeSchedulerProfile{ + { + SchedulerName: pointer.StringPtr("default-scheduler"), + PluginConfig: []v1beta2.PluginConfig{ + {Name: "FooPlugin"}, + }, + }, + }, + }, + }, + { + name: "two profiles", + config: &v1beta2.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + Profiles: []v1beta2.KubeSchedulerProfile{ + { + PluginConfig: []v1beta2.PluginConfig{ + {Name: "FooPlugin"}, + }, + }, + { + SchedulerName: pointer.StringPtr("custom-scheduler"), + Plugins: &v1beta2.Plugins{ + Bind: v1beta2.PluginSet{ + Enabled: []v1beta2.Plugin{ + {Name: "BarPlugin"}, + }, + }, + }, + }, + }, + }, + expected: &v1beta2.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + HealthzBindAddress: pointer.StringPtr("0.0.0.0:10251"), + MetricsBindAddress: pointer.StringPtr("0.0.0.0:10251"), + 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: []v1beta2.KubeSchedulerProfile{ + { + PluginConfig: []v1beta2.PluginConfig{ + {Name: "FooPlugin"}, + }, + }, + { + SchedulerName: pointer.StringPtr("custom-scheduler"), + Plugins: &v1beta2.Plugins{ + Bind: v1beta2.PluginSet{ + Enabled: []v1beta2.Plugin{ + {Name: "BarPlugin"}, + }, + }, + }, + }, + }, + }, + }, + { + name: "metrics and healthz address with no port", + config: &v1beta2.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + MetricsBindAddress: pointer.StringPtr("1.2.3.4"), + HealthzBindAddress: pointer.StringPtr("1.2.3.4"), + }, + expected: &v1beta2.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + HealthzBindAddress: pointer.StringPtr("1.2.3.4:10251"), + MetricsBindAddress: pointer.StringPtr("1.2.3.4:10251"), + 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: []v1beta2.KubeSchedulerProfile{ + {SchedulerName: pointer.StringPtr("default-scheduler")}, + }, + }, + }, + { + name: "metrics and healthz port with no address", + config: &v1beta2.KubeSchedulerConfiguration{ + MetricsBindAddress: pointer.StringPtr(":12345"), + HealthzBindAddress: pointer.StringPtr(":12345"), + }, + expected: &v1beta2.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + HealthzBindAddress: pointer.StringPtr("0.0.0.0:12345"), + MetricsBindAddress: pointer.StringPtr("0.0.0.0:12345"), + 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: []v1beta2.KubeSchedulerProfile{ + {SchedulerName: pointer.StringPtr("default-scheduler")}, + }, + }, + }, + { + name: "metrics and healthz with invalid IP", + config: &v1beta2.KubeSchedulerConfiguration{ + MetricsBindAddress: pointer.StringPtr("999.888.777"), + HealthzBindAddress: pointer.StringPtr("999.888.777"), + }, + expected: &v1beta2.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(16), + HealthzBindAddress: pointer.StringPtr("999.888.777"), + MetricsBindAddress: pointer.StringPtr("999.888.777"), + 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: []v1beta2.KubeSchedulerProfile{ + {SchedulerName: pointer.StringPtr("default-scheduler")}, + }, + }, + }, + { + name: "set non default parallelism", + config: &v1beta2.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(8), + }, + expected: &v1beta2.KubeSchedulerConfiguration{ + Parallelism: pointer.Int32Ptr(8), + HealthzBindAddress: pointer.StringPtr("0.0.0.0:10251"), + MetricsBindAddress: pointer.StringPtr("0.0.0.0:10251"), + 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: []v1beta2.KubeSchedulerProfile{ + {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: &v1beta2.DefaultPreemptionArgs{}, + want: &v1beta2.DefaultPreemptionArgs{ + MinCandidateNodesPercentage: pointer.Int32Ptr(10), + MinCandidateNodesAbsolute: pointer.Int32Ptr(100), + }, + }, + { + name: "DefaultPreemptionArgs with value", + in: &v1beta2.DefaultPreemptionArgs{ + MinCandidateNodesPercentage: pointer.Int32Ptr(50), + }, + want: &v1beta2.DefaultPreemptionArgs{ + MinCandidateNodesPercentage: pointer.Int32Ptr(50), + MinCandidateNodesAbsolute: pointer.Int32Ptr(100), + }, + }, + { + name: "InterPodAffinityArgs empty", + in: &v1beta2.InterPodAffinityArgs{}, + want: &v1beta2.InterPodAffinityArgs{ + HardPodAffinityWeight: pointer.Int32Ptr(1), + }, + }, + { + name: "InterPodAffinityArgs explicit 0", + in: &v1beta2.InterPodAffinityArgs{ + HardPodAffinityWeight: pointer.Int32Ptr(0), + }, + want: &v1beta2.InterPodAffinityArgs{ + HardPodAffinityWeight: pointer.Int32Ptr(0), + }, + }, + { + name: "InterPodAffinityArgs with value", + in: &v1beta2.InterPodAffinityArgs{ + HardPodAffinityWeight: pointer.Int32Ptr(5), + }, + want: &v1beta2.InterPodAffinityArgs{ + HardPodAffinityWeight: pointer.Int32Ptr(5), + }, + }, + { + name: "NodeResourcesLeastAllocatedArgs resources empty", + in: &v1beta2.NodeResourcesLeastAllocatedArgs{}, + want: &v1beta2.NodeResourcesLeastAllocatedArgs{ + Resources: []v1beta2.ResourceSpec{ + {Name: "cpu", Weight: 1}, + {Name: "memory", Weight: 1}, + }, + }, + }, + { + name: "NodeResourcesLeastAllocatedArgs resources with value", + in: &v1beta2.NodeResourcesLeastAllocatedArgs{ + Resources: []v1beta2.ResourceSpec{ + {Name: "resource", Weight: 2}, + }, + }, + want: &v1beta2.NodeResourcesLeastAllocatedArgs{ + Resources: []v1beta2.ResourceSpec{ + {Name: "resource", Weight: 2}, + }, + }, + }, + { + name: "NodeResourcesMostAllocatedArgs resources empty", + in: &v1beta2.NodeResourcesMostAllocatedArgs{}, + want: &v1beta2.NodeResourcesMostAllocatedArgs{ + Resources: []v1beta2.ResourceSpec{ + {Name: "cpu", Weight: 1}, + {Name: "memory", Weight: 1}, + }, + }, + }, + { + name: "NodeResourcesMostAllocatedArgs resources with value", + in: &v1beta2.NodeResourcesMostAllocatedArgs{ + Resources: []v1beta2.ResourceSpec{ + {Name: "resource", Weight: 2}, + }, + }, + want: &v1beta2.NodeResourcesMostAllocatedArgs{ + Resources: []v1beta2.ResourceSpec{ + {Name: "resource", Weight: 2}, + }, + }, + }, + { + name: "NodeResourcesMostAllocatedArgs resources empty", + in: &v1beta2.NodeResourcesMostAllocatedArgs{}, + want: &v1beta2.NodeResourcesMostAllocatedArgs{ + Resources: []v1beta2.ResourceSpec{ + {Name: "cpu", Weight: 1}, + {Name: "memory", Weight: 1}, + }, + }, + }, + { + name: "NodeResourcesMostAllocatedArgs resources with value", + in: &v1beta2.NodeResourcesMostAllocatedArgs{ + Resources: []v1beta2.ResourceSpec{ + {Name: "resource", Weight: 2}, + }, + }, + want: &v1beta2.NodeResourcesMostAllocatedArgs{ + Resources: []v1beta2.ResourceSpec{ + {Name: "resource", Weight: 2}, + }, + }, + }, + { + name: "PodTopologySpreadArgs resources empty", + in: &v1beta2.PodTopologySpreadArgs{}, + want: &v1beta2.PodTopologySpreadArgs{ + DefaultingType: v1beta2.SystemDefaulting, + }, + }, + { + name: "PodTopologySpreadArgs resources with value", + in: &v1beta2.PodTopologySpreadArgs{ + DefaultConstraints: []v1.TopologySpreadConstraint{ + { + TopologyKey: "planet", + WhenUnsatisfiable: v1.DoNotSchedule, + MaxSkew: 2, + }, + }, + }, + want: &v1beta2.PodTopologySpreadArgs{ + DefaultConstraints: []v1.TopologySpreadConstraint{ + { + TopologyKey: "planet", + WhenUnsatisfiable: v1.DoNotSchedule, + MaxSkew: 2, + }, + }, + DefaultingType: v1beta2.SystemDefaulting, + }, + }, + { + name: "PodTopologySpreadArgs empty, DefaultPodTopologySpread feature disabled", + features: map[featuregate.Feature]bool{ + features.DefaultPodTopologySpread: false, + }, + in: &v1beta2.PodTopologySpreadArgs{}, + want: &v1beta2.PodTopologySpreadArgs{ + DefaultingType: v1beta2.ListDefaulting, + }, + }, + } + 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/v1beta2/doc.go b/pkg/scheduler/apis/config/v1beta2/doc.go new file mode 100644 index 00000000000..bc0f1a695f6 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta2/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/v1beta2 +// +k8s:defaulter-gen=TypeMeta +// +k8s:defaulter-gen-input=../../../../../vendor/k8s.io/kube-scheduler/config/v1beta2 +// +groupName=kubescheduler.config.k8s.io + +package v1beta2 // import "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta2" diff --git a/pkg/scheduler/apis/config/v1beta2/register.go b/pkg/scheduler/apis/config/v1beta2/register.go new file mode 100644 index 00000000000..b8ca76de5f5 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta2/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 v1beta2 + +import ( + "k8s.io/kube-scheduler/config/v1beta2" +) + +// GroupName is the group name used in this package +const GroupName = v1beta2.GroupName + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = v1beta2.SchemeGroupVersion + +var ( + // localSchemeBuilder extends the SchemeBuilder instance with the external types. In this package, + // defaulting and conversion init funcs are registered as well. + localSchemeBuilder = &v1beta2.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/v1beta2/zz_generated.conversion.go b/pkg/scheduler/apis/config/v1beta2/zz_generated.conversion.go new file mode 100644 index 00000000000..a8b8c3b2500 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta2/zz_generated.conversion.go @@ -0,0 +1,863 @@ +// +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 v1beta2 + +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" + v1beta2 "k8s.io/kube-scheduler/config/v1beta2" + 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((*v1beta2.DefaultPreemptionArgs)(nil), (*config.DefaultPreemptionArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_DefaultPreemptionArgs_To_config_DefaultPreemptionArgs(a.(*v1beta2.DefaultPreemptionArgs), b.(*config.DefaultPreemptionArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.DefaultPreemptionArgs)(nil), (*v1beta2.DefaultPreemptionArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_DefaultPreemptionArgs_To_v1beta2_DefaultPreemptionArgs(a.(*config.DefaultPreemptionArgs), b.(*v1beta2.DefaultPreemptionArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.Extender)(nil), (*config.Extender)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_Extender_To_config_Extender(a.(*v1beta2.Extender), b.(*config.Extender), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.Extender)(nil), (*v1beta2.Extender)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_Extender_To_v1beta2_Extender(a.(*config.Extender), b.(*v1beta2.Extender), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.InterPodAffinityArgs)(nil), (*config.InterPodAffinityArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_InterPodAffinityArgs_To_config_InterPodAffinityArgs(a.(*v1beta2.InterPodAffinityArgs), b.(*config.InterPodAffinityArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.InterPodAffinityArgs)(nil), (*v1beta2.InterPodAffinityArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_InterPodAffinityArgs_To_v1beta2_InterPodAffinityArgs(a.(*config.InterPodAffinityArgs), b.(*v1beta2.InterPodAffinityArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.KubeSchedulerProfile)(nil), (*config.KubeSchedulerProfile)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_KubeSchedulerProfile_To_config_KubeSchedulerProfile(a.(*v1beta2.KubeSchedulerProfile), b.(*config.KubeSchedulerProfile), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.KubeSchedulerProfile)(nil), (*v1beta2.KubeSchedulerProfile)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_KubeSchedulerProfile_To_v1beta2_KubeSchedulerProfile(a.(*config.KubeSchedulerProfile), b.(*v1beta2.KubeSchedulerProfile), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.NodeAffinityArgs)(nil), (*config.NodeAffinityArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_NodeAffinityArgs_To_config_NodeAffinityArgs(a.(*v1beta2.NodeAffinityArgs), b.(*config.NodeAffinityArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.NodeAffinityArgs)(nil), (*v1beta2.NodeAffinityArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_NodeAffinityArgs_To_v1beta2_NodeAffinityArgs(a.(*config.NodeAffinityArgs), b.(*v1beta2.NodeAffinityArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.NodeResourcesFitArgs)(nil), (*config.NodeResourcesFitArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_NodeResourcesFitArgs_To_config_NodeResourcesFitArgs(a.(*v1beta2.NodeResourcesFitArgs), b.(*config.NodeResourcesFitArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.NodeResourcesFitArgs)(nil), (*v1beta2.NodeResourcesFitArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_NodeResourcesFitArgs_To_v1beta2_NodeResourcesFitArgs(a.(*config.NodeResourcesFitArgs), b.(*v1beta2.NodeResourcesFitArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.NodeResourcesLeastAllocatedArgs)(nil), (*config.NodeResourcesLeastAllocatedArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_NodeResourcesLeastAllocatedArgs_To_config_NodeResourcesLeastAllocatedArgs(a.(*v1beta2.NodeResourcesLeastAllocatedArgs), b.(*config.NodeResourcesLeastAllocatedArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.NodeResourcesLeastAllocatedArgs)(nil), (*v1beta2.NodeResourcesLeastAllocatedArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_NodeResourcesLeastAllocatedArgs_To_v1beta2_NodeResourcesLeastAllocatedArgs(a.(*config.NodeResourcesLeastAllocatedArgs), b.(*v1beta2.NodeResourcesLeastAllocatedArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.NodeResourcesMostAllocatedArgs)(nil), (*config.NodeResourcesMostAllocatedArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_NodeResourcesMostAllocatedArgs_To_config_NodeResourcesMostAllocatedArgs(a.(*v1beta2.NodeResourcesMostAllocatedArgs), b.(*config.NodeResourcesMostAllocatedArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.NodeResourcesMostAllocatedArgs)(nil), (*v1beta2.NodeResourcesMostAllocatedArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_NodeResourcesMostAllocatedArgs_To_v1beta2_NodeResourcesMostAllocatedArgs(a.(*config.NodeResourcesMostAllocatedArgs), b.(*v1beta2.NodeResourcesMostAllocatedArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.Plugin)(nil), (*config.Plugin)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_Plugin_To_config_Plugin(a.(*v1beta2.Plugin), b.(*config.Plugin), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.Plugin)(nil), (*v1beta2.Plugin)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_Plugin_To_v1beta2_Plugin(a.(*config.Plugin), b.(*v1beta2.Plugin), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.PluginConfig)(nil), (*config.PluginConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_PluginConfig_To_config_PluginConfig(a.(*v1beta2.PluginConfig), b.(*config.PluginConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.PluginConfig)(nil), (*v1beta2.PluginConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_PluginConfig_To_v1beta2_PluginConfig(a.(*config.PluginConfig), b.(*v1beta2.PluginConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.PluginSet)(nil), (*config.PluginSet)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_PluginSet_To_config_PluginSet(a.(*v1beta2.PluginSet), b.(*config.PluginSet), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.PluginSet)(nil), (*v1beta2.PluginSet)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_PluginSet_To_v1beta2_PluginSet(a.(*config.PluginSet), b.(*v1beta2.PluginSet), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.Plugins)(nil), (*config.Plugins)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_Plugins_To_config_Plugins(a.(*v1beta2.Plugins), b.(*config.Plugins), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.Plugins)(nil), (*v1beta2.Plugins)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_Plugins_To_v1beta2_Plugins(a.(*config.Plugins), b.(*v1beta2.Plugins), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.PodTopologySpreadArgs)(nil), (*config.PodTopologySpreadArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs(a.(*v1beta2.PodTopologySpreadArgs), b.(*config.PodTopologySpreadArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.PodTopologySpreadArgs)(nil), (*v1beta2.PodTopologySpreadArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_PodTopologySpreadArgs_To_v1beta2_PodTopologySpreadArgs(a.(*config.PodTopologySpreadArgs), b.(*v1beta2.PodTopologySpreadArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.RequestedToCapacityRatioArgs)(nil), (*config.RequestedToCapacityRatioArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_RequestedToCapacityRatioArgs_To_config_RequestedToCapacityRatioArgs(a.(*v1beta2.RequestedToCapacityRatioArgs), b.(*config.RequestedToCapacityRatioArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.RequestedToCapacityRatioArgs)(nil), (*v1beta2.RequestedToCapacityRatioArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_RequestedToCapacityRatioArgs_To_v1beta2_RequestedToCapacityRatioArgs(a.(*config.RequestedToCapacityRatioArgs), b.(*v1beta2.RequestedToCapacityRatioArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.ResourceSpec)(nil), (*config.ResourceSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_ResourceSpec_To_config_ResourceSpec(a.(*v1beta2.ResourceSpec), b.(*config.ResourceSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.ResourceSpec)(nil), (*v1beta2.ResourceSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_ResourceSpec_To_v1beta2_ResourceSpec(a.(*config.ResourceSpec), b.(*v1beta2.ResourceSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.UtilizationShapePoint)(nil), (*config.UtilizationShapePoint)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_UtilizationShapePoint_To_config_UtilizationShapePoint(a.(*v1beta2.UtilizationShapePoint), b.(*config.UtilizationShapePoint), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.UtilizationShapePoint)(nil), (*v1beta2.UtilizationShapePoint)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_UtilizationShapePoint_To_v1beta2_UtilizationShapePoint(a.(*config.UtilizationShapePoint), b.(*v1beta2.UtilizationShapePoint), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.VolumeBindingArgs)(nil), (*config.VolumeBindingArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_VolumeBindingArgs_To_config_VolumeBindingArgs(a.(*v1beta2.VolumeBindingArgs), b.(*config.VolumeBindingArgs), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.VolumeBindingArgs)(nil), (*v1beta2.VolumeBindingArgs)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_VolumeBindingArgs_To_v1beta2_VolumeBindingArgs(a.(*config.VolumeBindingArgs), b.(*v1beta2.VolumeBindingArgs), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*config.KubeSchedulerConfiguration)(nil), (*v1beta2.KubeSchedulerConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_KubeSchedulerConfiguration_To_v1beta2_KubeSchedulerConfiguration(a.(*config.KubeSchedulerConfiguration), b.(*v1beta2.KubeSchedulerConfiguration), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta2.KubeSchedulerConfiguration)(nil), (*config.KubeSchedulerConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(a.(*v1beta2.KubeSchedulerConfiguration), b.(*config.KubeSchedulerConfiguration), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta2_DefaultPreemptionArgs_To_config_DefaultPreemptionArgs(in *v1beta2.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_v1beta2_DefaultPreemptionArgs_To_config_DefaultPreemptionArgs is an autogenerated conversion function. +func Convert_v1beta2_DefaultPreemptionArgs_To_config_DefaultPreemptionArgs(in *v1beta2.DefaultPreemptionArgs, out *config.DefaultPreemptionArgs, s conversion.Scope) error { + return autoConvert_v1beta2_DefaultPreemptionArgs_To_config_DefaultPreemptionArgs(in, out, s) +} + +func autoConvert_config_DefaultPreemptionArgs_To_v1beta2_DefaultPreemptionArgs(in *config.DefaultPreemptionArgs, out *v1beta2.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_v1beta2_DefaultPreemptionArgs is an autogenerated conversion function. +func Convert_config_DefaultPreemptionArgs_To_v1beta2_DefaultPreemptionArgs(in *config.DefaultPreemptionArgs, out *v1beta2.DefaultPreemptionArgs, s conversion.Scope) error { + return autoConvert_config_DefaultPreemptionArgs_To_v1beta2_DefaultPreemptionArgs(in, out, s) +} + +func autoConvert_v1beta2_Extender_To_config_Extender(in *v1beta2.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_v1beta2_Extender_To_config_Extender is an autogenerated conversion function. +func Convert_v1beta2_Extender_To_config_Extender(in *v1beta2.Extender, out *config.Extender, s conversion.Scope) error { + return autoConvert_v1beta2_Extender_To_config_Extender(in, out, s) +} + +func autoConvert_config_Extender_To_v1beta2_Extender(in *config.Extender, out *v1beta2.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_v1beta2_Extender is an autogenerated conversion function. +func Convert_config_Extender_To_v1beta2_Extender(in *config.Extender, out *v1beta2.Extender, s conversion.Scope) error { + return autoConvert_config_Extender_To_v1beta2_Extender(in, out, s) +} + +func autoConvert_v1beta2_InterPodAffinityArgs_To_config_InterPodAffinityArgs(in *v1beta2.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_v1beta2_InterPodAffinityArgs_To_config_InterPodAffinityArgs is an autogenerated conversion function. +func Convert_v1beta2_InterPodAffinityArgs_To_config_InterPodAffinityArgs(in *v1beta2.InterPodAffinityArgs, out *config.InterPodAffinityArgs, s conversion.Scope) error { + return autoConvert_v1beta2_InterPodAffinityArgs_To_config_InterPodAffinityArgs(in, out, s) +} + +func autoConvert_config_InterPodAffinityArgs_To_v1beta2_InterPodAffinityArgs(in *config.InterPodAffinityArgs, out *v1beta2.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_v1beta2_InterPodAffinityArgs is an autogenerated conversion function. +func Convert_config_InterPodAffinityArgs_To_v1beta2_InterPodAffinityArgs(in *config.InterPodAffinityArgs, out *v1beta2.InterPodAffinityArgs, s conversion.Scope) error { + return autoConvert_config_InterPodAffinityArgs_To_v1beta2_InterPodAffinityArgs(in, out, s) +} + +func autoConvert_v1beta2_KubeSchedulerConfiguration_To_config_KubeSchedulerConfiguration(in *v1beta2.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 := v1.Convert_Pointer_string_To_string(&in.HealthzBindAddress, &out.HealthzBindAddress, s); err != nil { + return err + } + if err := v1.Convert_Pointer_string_To_string(&in.MetricsBindAddress, &out.MetricsBindAddress, 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_v1beta2_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_v1beta2_KubeSchedulerConfiguration(in *config.KubeSchedulerConfiguration, out *v1beta2.KubeSchedulerConfiguration, s conversion.Scope) error { + if err := v1.Convert_int32_To_Pointer_int32(&in.Parallelism, &out.Parallelism, s); err != nil { + return err + } + // WARNING: in.AlgorithmSource requires manual conversion: does not exist in peer-type + 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 + } + if err := v1.Convert_string_To_Pointer_string(&in.HealthzBindAddress, &out.HealthzBindAddress, s); err != nil { + return err + } + if err := v1.Convert_string_To_Pointer_string(&in.MetricsBindAddress, &out.MetricsBindAddress, s); err != nil { + return err + } + 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([]v1beta2.KubeSchedulerProfile, len(*in)) + for i := range *in { + if err := Convert_config_KubeSchedulerProfile_To_v1beta2_KubeSchedulerProfile(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Profiles = nil + } + out.Extenders = *(*[]v1beta2.Extender)(unsafe.Pointer(&in.Extenders)) + return nil +} + +func autoConvert_v1beta2_KubeSchedulerProfile_To_config_KubeSchedulerProfile(in *v1beta2.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_v1beta2_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_v1beta2_PluginConfig_To_config_PluginConfig(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.PluginConfig = nil + } + return nil +} + +// Convert_v1beta2_KubeSchedulerProfile_To_config_KubeSchedulerProfile is an autogenerated conversion function. +func Convert_v1beta2_KubeSchedulerProfile_To_config_KubeSchedulerProfile(in *v1beta2.KubeSchedulerProfile, out *config.KubeSchedulerProfile, s conversion.Scope) error { + return autoConvert_v1beta2_KubeSchedulerProfile_To_config_KubeSchedulerProfile(in, out, s) +} + +func autoConvert_config_KubeSchedulerProfile_To_v1beta2_KubeSchedulerProfile(in *config.KubeSchedulerProfile, out *v1beta2.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(v1beta2.Plugins) + if err := Convert_config_Plugins_To_v1beta2_Plugins(*in, *out, s); err != nil { + return err + } + } else { + out.Plugins = nil + } + if in.PluginConfig != nil { + in, out := &in.PluginConfig, &out.PluginConfig + *out = make([]v1beta2.PluginConfig, len(*in)) + for i := range *in { + if err := Convert_config_PluginConfig_To_v1beta2_PluginConfig(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.PluginConfig = nil + } + return nil +} + +// Convert_config_KubeSchedulerProfile_To_v1beta2_KubeSchedulerProfile is an autogenerated conversion function. +func Convert_config_KubeSchedulerProfile_To_v1beta2_KubeSchedulerProfile(in *config.KubeSchedulerProfile, out *v1beta2.KubeSchedulerProfile, s conversion.Scope) error { + return autoConvert_config_KubeSchedulerProfile_To_v1beta2_KubeSchedulerProfile(in, out, s) +} + +func autoConvert_v1beta2_NodeAffinityArgs_To_config_NodeAffinityArgs(in *v1beta2.NodeAffinityArgs, out *config.NodeAffinityArgs, s conversion.Scope) error { + out.AddedAffinity = (*corev1.NodeAffinity)(unsafe.Pointer(in.AddedAffinity)) + return nil +} + +// Convert_v1beta2_NodeAffinityArgs_To_config_NodeAffinityArgs is an autogenerated conversion function. +func Convert_v1beta2_NodeAffinityArgs_To_config_NodeAffinityArgs(in *v1beta2.NodeAffinityArgs, out *config.NodeAffinityArgs, s conversion.Scope) error { + return autoConvert_v1beta2_NodeAffinityArgs_To_config_NodeAffinityArgs(in, out, s) +} + +func autoConvert_config_NodeAffinityArgs_To_v1beta2_NodeAffinityArgs(in *config.NodeAffinityArgs, out *v1beta2.NodeAffinityArgs, s conversion.Scope) error { + out.AddedAffinity = (*corev1.NodeAffinity)(unsafe.Pointer(in.AddedAffinity)) + return nil +} + +// Convert_config_NodeAffinityArgs_To_v1beta2_NodeAffinityArgs is an autogenerated conversion function. +func Convert_config_NodeAffinityArgs_To_v1beta2_NodeAffinityArgs(in *config.NodeAffinityArgs, out *v1beta2.NodeAffinityArgs, s conversion.Scope) error { + return autoConvert_config_NodeAffinityArgs_To_v1beta2_NodeAffinityArgs(in, out, s) +} + +func autoConvert_v1beta2_NodeResourcesFitArgs_To_config_NodeResourcesFitArgs(in *v1beta2.NodeResourcesFitArgs, out *config.NodeResourcesFitArgs, s conversion.Scope) error { + out.IgnoredResources = *(*[]string)(unsafe.Pointer(&in.IgnoredResources)) + out.IgnoredResourceGroups = *(*[]string)(unsafe.Pointer(&in.IgnoredResourceGroups)) + return nil +} + +// Convert_v1beta2_NodeResourcesFitArgs_To_config_NodeResourcesFitArgs is an autogenerated conversion function. +func Convert_v1beta2_NodeResourcesFitArgs_To_config_NodeResourcesFitArgs(in *v1beta2.NodeResourcesFitArgs, out *config.NodeResourcesFitArgs, s conversion.Scope) error { + return autoConvert_v1beta2_NodeResourcesFitArgs_To_config_NodeResourcesFitArgs(in, out, s) +} + +func autoConvert_config_NodeResourcesFitArgs_To_v1beta2_NodeResourcesFitArgs(in *config.NodeResourcesFitArgs, out *v1beta2.NodeResourcesFitArgs, s conversion.Scope) error { + out.IgnoredResources = *(*[]string)(unsafe.Pointer(&in.IgnoredResources)) + out.IgnoredResourceGroups = *(*[]string)(unsafe.Pointer(&in.IgnoredResourceGroups)) + return nil +} + +// Convert_config_NodeResourcesFitArgs_To_v1beta2_NodeResourcesFitArgs is an autogenerated conversion function. +func Convert_config_NodeResourcesFitArgs_To_v1beta2_NodeResourcesFitArgs(in *config.NodeResourcesFitArgs, out *v1beta2.NodeResourcesFitArgs, s conversion.Scope) error { + return autoConvert_config_NodeResourcesFitArgs_To_v1beta2_NodeResourcesFitArgs(in, out, s) +} + +func autoConvert_v1beta2_NodeResourcesLeastAllocatedArgs_To_config_NodeResourcesLeastAllocatedArgs(in *v1beta2.NodeResourcesLeastAllocatedArgs, out *config.NodeResourcesLeastAllocatedArgs, s conversion.Scope) error { + out.Resources = *(*[]config.ResourceSpec)(unsafe.Pointer(&in.Resources)) + return nil +} + +// Convert_v1beta2_NodeResourcesLeastAllocatedArgs_To_config_NodeResourcesLeastAllocatedArgs is an autogenerated conversion function. +func Convert_v1beta2_NodeResourcesLeastAllocatedArgs_To_config_NodeResourcesLeastAllocatedArgs(in *v1beta2.NodeResourcesLeastAllocatedArgs, out *config.NodeResourcesLeastAllocatedArgs, s conversion.Scope) error { + return autoConvert_v1beta2_NodeResourcesLeastAllocatedArgs_To_config_NodeResourcesLeastAllocatedArgs(in, out, s) +} + +func autoConvert_config_NodeResourcesLeastAllocatedArgs_To_v1beta2_NodeResourcesLeastAllocatedArgs(in *config.NodeResourcesLeastAllocatedArgs, out *v1beta2.NodeResourcesLeastAllocatedArgs, s conversion.Scope) error { + out.Resources = *(*[]v1beta2.ResourceSpec)(unsafe.Pointer(&in.Resources)) + return nil +} + +// Convert_config_NodeResourcesLeastAllocatedArgs_To_v1beta2_NodeResourcesLeastAllocatedArgs is an autogenerated conversion function. +func Convert_config_NodeResourcesLeastAllocatedArgs_To_v1beta2_NodeResourcesLeastAllocatedArgs(in *config.NodeResourcesLeastAllocatedArgs, out *v1beta2.NodeResourcesLeastAllocatedArgs, s conversion.Scope) error { + return autoConvert_config_NodeResourcesLeastAllocatedArgs_To_v1beta2_NodeResourcesLeastAllocatedArgs(in, out, s) +} + +func autoConvert_v1beta2_NodeResourcesMostAllocatedArgs_To_config_NodeResourcesMostAllocatedArgs(in *v1beta2.NodeResourcesMostAllocatedArgs, out *config.NodeResourcesMostAllocatedArgs, s conversion.Scope) error { + out.Resources = *(*[]config.ResourceSpec)(unsafe.Pointer(&in.Resources)) + return nil +} + +// Convert_v1beta2_NodeResourcesMostAllocatedArgs_To_config_NodeResourcesMostAllocatedArgs is an autogenerated conversion function. +func Convert_v1beta2_NodeResourcesMostAllocatedArgs_To_config_NodeResourcesMostAllocatedArgs(in *v1beta2.NodeResourcesMostAllocatedArgs, out *config.NodeResourcesMostAllocatedArgs, s conversion.Scope) error { + return autoConvert_v1beta2_NodeResourcesMostAllocatedArgs_To_config_NodeResourcesMostAllocatedArgs(in, out, s) +} + +func autoConvert_config_NodeResourcesMostAllocatedArgs_To_v1beta2_NodeResourcesMostAllocatedArgs(in *config.NodeResourcesMostAllocatedArgs, out *v1beta2.NodeResourcesMostAllocatedArgs, s conversion.Scope) error { + out.Resources = *(*[]v1beta2.ResourceSpec)(unsafe.Pointer(&in.Resources)) + return nil +} + +// Convert_config_NodeResourcesMostAllocatedArgs_To_v1beta2_NodeResourcesMostAllocatedArgs is an autogenerated conversion function. +func Convert_config_NodeResourcesMostAllocatedArgs_To_v1beta2_NodeResourcesMostAllocatedArgs(in *config.NodeResourcesMostAllocatedArgs, out *v1beta2.NodeResourcesMostAllocatedArgs, s conversion.Scope) error { + return autoConvert_config_NodeResourcesMostAllocatedArgs_To_v1beta2_NodeResourcesMostAllocatedArgs(in, out, s) +} + +func autoConvert_v1beta2_Plugin_To_config_Plugin(in *v1beta2.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_v1beta2_Plugin_To_config_Plugin is an autogenerated conversion function. +func Convert_v1beta2_Plugin_To_config_Plugin(in *v1beta2.Plugin, out *config.Plugin, s conversion.Scope) error { + return autoConvert_v1beta2_Plugin_To_config_Plugin(in, out, s) +} + +func autoConvert_config_Plugin_To_v1beta2_Plugin(in *config.Plugin, out *v1beta2.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_v1beta2_Plugin is an autogenerated conversion function. +func Convert_config_Plugin_To_v1beta2_Plugin(in *config.Plugin, out *v1beta2.Plugin, s conversion.Scope) error { + return autoConvert_config_Plugin_To_v1beta2_Plugin(in, out, s) +} + +func autoConvert_v1beta2_PluginConfig_To_config_PluginConfig(in *v1beta2.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_v1beta2_PluginConfig_To_config_PluginConfig is an autogenerated conversion function. +func Convert_v1beta2_PluginConfig_To_config_PluginConfig(in *v1beta2.PluginConfig, out *config.PluginConfig, s conversion.Scope) error { + return autoConvert_v1beta2_PluginConfig_To_config_PluginConfig(in, out, s) +} + +func autoConvert_config_PluginConfig_To_v1beta2_PluginConfig(in *config.PluginConfig, out *v1beta2.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_v1beta2_PluginConfig is an autogenerated conversion function. +func Convert_config_PluginConfig_To_v1beta2_PluginConfig(in *config.PluginConfig, out *v1beta2.PluginConfig, s conversion.Scope) error { + return autoConvert_config_PluginConfig_To_v1beta2_PluginConfig(in, out, s) +} + +func autoConvert_v1beta2_PluginSet_To_config_PluginSet(in *v1beta2.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_v1beta2_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_v1beta2_Plugin_To_config_Plugin(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Disabled = nil + } + return nil +} + +// Convert_v1beta2_PluginSet_To_config_PluginSet is an autogenerated conversion function. +func Convert_v1beta2_PluginSet_To_config_PluginSet(in *v1beta2.PluginSet, out *config.PluginSet, s conversion.Scope) error { + return autoConvert_v1beta2_PluginSet_To_config_PluginSet(in, out, s) +} + +func autoConvert_config_PluginSet_To_v1beta2_PluginSet(in *config.PluginSet, out *v1beta2.PluginSet, s conversion.Scope) error { + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = make([]v1beta2.Plugin, len(*in)) + for i := range *in { + if err := Convert_config_Plugin_To_v1beta2_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([]v1beta2.Plugin, len(*in)) + for i := range *in { + if err := Convert_config_Plugin_To_v1beta2_Plugin(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Disabled = nil + } + return nil +} + +// Convert_config_PluginSet_To_v1beta2_PluginSet is an autogenerated conversion function. +func Convert_config_PluginSet_To_v1beta2_PluginSet(in *config.PluginSet, out *v1beta2.PluginSet, s conversion.Scope) error { + return autoConvert_config_PluginSet_To_v1beta2_PluginSet(in, out, s) +} + +func autoConvert_v1beta2_Plugins_To_config_Plugins(in *v1beta2.Plugins, out *config.Plugins, s conversion.Scope) error { + if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.QueueSort, &out.QueueSort, s); err != nil { + return err + } + if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.PreFilter, &out.PreFilter, s); err != nil { + return err + } + if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.Filter, &out.Filter, s); err != nil { + return err + } + if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.PostFilter, &out.PostFilter, s); err != nil { + return err + } + if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.PreScore, &out.PreScore, s); err != nil { + return err + } + if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.Score, &out.Score, s); err != nil { + return err + } + if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.Reserve, &out.Reserve, s); err != nil { + return err + } + if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.Permit, &out.Permit, s); err != nil { + return err + } + if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.PreBind, &out.PreBind, s); err != nil { + return err + } + if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.Bind, &out.Bind, s); err != nil { + return err + } + if err := Convert_v1beta2_PluginSet_To_config_PluginSet(&in.PostBind, &out.PostBind, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta2_Plugins_To_config_Plugins is an autogenerated conversion function. +func Convert_v1beta2_Plugins_To_config_Plugins(in *v1beta2.Plugins, out *config.Plugins, s conversion.Scope) error { + return autoConvert_v1beta2_Plugins_To_config_Plugins(in, out, s) +} + +func autoConvert_config_Plugins_To_v1beta2_Plugins(in *config.Plugins, out *v1beta2.Plugins, s conversion.Scope) error { + if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.QueueSort, &out.QueueSort, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.PreFilter, &out.PreFilter, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.Filter, &out.Filter, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.PostFilter, &out.PostFilter, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.PreScore, &out.PreScore, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.Score, &out.Score, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.Reserve, &out.Reserve, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.Permit, &out.Permit, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.PreBind, &out.PreBind, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.Bind, &out.Bind, s); err != nil { + return err + } + if err := Convert_config_PluginSet_To_v1beta2_PluginSet(&in.PostBind, &out.PostBind, s); err != nil { + return err + } + return nil +} + +// Convert_config_Plugins_To_v1beta2_Plugins is an autogenerated conversion function. +func Convert_config_Plugins_To_v1beta2_Plugins(in *config.Plugins, out *v1beta2.Plugins, s conversion.Scope) error { + return autoConvert_config_Plugins_To_v1beta2_Plugins(in, out, s) +} + +func autoConvert_v1beta2_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs(in *v1beta2.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_v1beta2_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs is an autogenerated conversion function. +func Convert_v1beta2_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs(in *v1beta2.PodTopologySpreadArgs, out *config.PodTopologySpreadArgs, s conversion.Scope) error { + return autoConvert_v1beta2_PodTopologySpreadArgs_To_config_PodTopologySpreadArgs(in, out, s) +} + +func autoConvert_config_PodTopologySpreadArgs_To_v1beta2_PodTopologySpreadArgs(in *config.PodTopologySpreadArgs, out *v1beta2.PodTopologySpreadArgs, s conversion.Scope) error { + out.DefaultConstraints = *(*[]corev1.TopologySpreadConstraint)(unsafe.Pointer(&in.DefaultConstraints)) + out.DefaultingType = v1beta2.PodTopologySpreadConstraintsDefaulting(in.DefaultingType) + return nil +} + +// Convert_config_PodTopologySpreadArgs_To_v1beta2_PodTopologySpreadArgs is an autogenerated conversion function. +func Convert_config_PodTopologySpreadArgs_To_v1beta2_PodTopologySpreadArgs(in *config.PodTopologySpreadArgs, out *v1beta2.PodTopologySpreadArgs, s conversion.Scope) error { + return autoConvert_config_PodTopologySpreadArgs_To_v1beta2_PodTopologySpreadArgs(in, out, s) +} + +func autoConvert_v1beta2_RequestedToCapacityRatioArgs_To_config_RequestedToCapacityRatioArgs(in *v1beta2.RequestedToCapacityRatioArgs, out *config.RequestedToCapacityRatioArgs, s conversion.Scope) error { + out.Shape = *(*[]config.UtilizationShapePoint)(unsafe.Pointer(&in.Shape)) + out.Resources = *(*[]config.ResourceSpec)(unsafe.Pointer(&in.Resources)) + return nil +} + +// Convert_v1beta2_RequestedToCapacityRatioArgs_To_config_RequestedToCapacityRatioArgs is an autogenerated conversion function. +func Convert_v1beta2_RequestedToCapacityRatioArgs_To_config_RequestedToCapacityRatioArgs(in *v1beta2.RequestedToCapacityRatioArgs, out *config.RequestedToCapacityRatioArgs, s conversion.Scope) error { + return autoConvert_v1beta2_RequestedToCapacityRatioArgs_To_config_RequestedToCapacityRatioArgs(in, out, s) +} + +func autoConvert_config_RequestedToCapacityRatioArgs_To_v1beta2_RequestedToCapacityRatioArgs(in *config.RequestedToCapacityRatioArgs, out *v1beta2.RequestedToCapacityRatioArgs, s conversion.Scope) error { + out.Shape = *(*[]v1beta2.UtilizationShapePoint)(unsafe.Pointer(&in.Shape)) + out.Resources = *(*[]v1beta2.ResourceSpec)(unsafe.Pointer(&in.Resources)) + return nil +} + +// Convert_config_RequestedToCapacityRatioArgs_To_v1beta2_RequestedToCapacityRatioArgs is an autogenerated conversion function. +func Convert_config_RequestedToCapacityRatioArgs_To_v1beta2_RequestedToCapacityRatioArgs(in *config.RequestedToCapacityRatioArgs, out *v1beta2.RequestedToCapacityRatioArgs, s conversion.Scope) error { + return autoConvert_config_RequestedToCapacityRatioArgs_To_v1beta2_RequestedToCapacityRatioArgs(in, out, s) +} + +func autoConvert_v1beta2_ResourceSpec_To_config_ResourceSpec(in *v1beta2.ResourceSpec, out *config.ResourceSpec, s conversion.Scope) error { + out.Name = in.Name + out.Weight = in.Weight + return nil +} + +// Convert_v1beta2_ResourceSpec_To_config_ResourceSpec is an autogenerated conversion function. +func Convert_v1beta2_ResourceSpec_To_config_ResourceSpec(in *v1beta2.ResourceSpec, out *config.ResourceSpec, s conversion.Scope) error { + return autoConvert_v1beta2_ResourceSpec_To_config_ResourceSpec(in, out, s) +} + +func autoConvert_config_ResourceSpec_To_v1beta2_ResourceSpec(in *config.ResourceSpec, out *v1beta2.ResourceSpec, s conversion.Scope) error { + out.Name = in.Name + out.Weight = in.Weight + return nil +} + +// Convert_config_ResourceSpec_To_v1beta2_ResourceSpec is an autogenerated conversion function. +func Convert_config_ResourceSpec_To_v1beta2_ResourceSpec(in *config.ResourceSpec, out *v1beta2.ResourceSpec, s conversion.Scope) error { + return autoConvert_config_ResourceSpec_To_v1beta2_ResourceSpec(in, out, s) +} + +func autoConvert_v1beta2_UtilizationShapePoint_To_config_UtilizationShapePoint(in *v1beta2.UtilizationShapePoint, out *config.UtilizationShapePoint, s conversion.Scope) error { + out.Utilization = in.Utilization + out.Score = in.Score + return nil +} + +// Convert_v1beta2_UtilizationShapePoint_To_config_UtilizationShapePoint is an autogenerated conversion function. +func Convert_v1beta2_UtilizationShapePoint_To_config_UtilizationShapePoint(in *v1beta2.UtilizationShapePoint, out *config.UtilizationShapePoint, s conversion.Scope) error { + return autoConvert_v1beta2_UtilizationShapePoint_To_config_UtilizationShapePoint(in, out, s) +} + +func autoConvert_config_UtilizationShapePoint_To_v1beta2_UtilizationShapePoint(in *config.UtilizationShapePoint, out *v1beta2.UtilizationShapePoint, s conversion.Scope) error { + out.Utilization = in.Utilization + out.Score = in.Score + return nil +} + +// Convert_config_UtilizationShapePoint_To_v1beta2_UtilizationShapePoint is an autogenerated conversion function. +func Convert_config_UtilizationShapePoint_To_v1beta2_UtilizationShapePoint(in *config.UtilizationShapePoint, out *v1beta2.UtilizationShapePoint, s conversion.Scope) error { + return autoConvert_config_UtilizationShapePoint_To_v1beta2_UtilizationShapePoint(in, out, s) +} + +func autoConvert_v1beta2_VolumeBindingArgs_To_config_VolumeBindingArgs(in *v1beta2.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 + } + return nil +} + +// Convert_v1beta2_VolumeBindingArgs_To_config_VolumeBindingArgs is an autogenerated conversion function. +func Convert_v1beta2_VolumeBindingArgs_To_config_VolumeBindingArgs(in *v1beta2.VolumeBindingArgs, out *config.VolumeBindingArgs, s conversion.Scope) error { + return autoConvert_v1beta2_VolumeBindingArgs_To_config_VolumeBindingArgs(in, out, s) +} + +func autoConvert_config_VolumeBindingArgs_To_v1beta2_VolumeBindingArgs(in *config.VolumeBindingArgs, out *v1beta2.VolumeBindingArgs, s conversion.Scope) error { + if err := v1.Convert_int64_To_Pointer_int64(&in.BindTimeoutSeconds, &out.BindTimeoutSeconds, s); err != nil { + return err + } + return nil +} + +// Convert_config_VolumeBindingArgs_To_v1beta2_VolumeBindingArgs is an autogenerated conversion function. +func Convert_config_VolumeBindingArgs_To_v1beta2_VolumeBindingArgs(in *config.VolumeBindingArgs, out *v1beta2.VolumeBindingArgs, s conversion.Scope) error { + return autoConvert_config_VolumeBindingArgs_To_v1beta2_VolumeBindingArgs(in, out, s) +} diff --git a/pkg/scheduler/apis/config/v1beta2/zz_generated.deepcopy.go b/pkg/scheduler/apis/config/v1beta2/zz_generated.deepcopy.go new file mode 100644 index 00000000000..8465e09932a --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta2/zz_generated.deepcopy.go @@ -0,0 +1,21 @@ +// +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 v1beta2 diff --git a/pkg/scheduler/apis/config/v1beta2/zz_generated.defaults.go b/pkg/scheduler/apis/config/v1beta2/zz_generated.defaults.go new file mode 100644 index 00000000000..4aa5e3b0257 --- /dev/null +++ b/pkg/scheduler/apis/config/v1beta2/zz_generated.defaults.go @@ -0,0 +1,81 @@ +// +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 v1beta2 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + v1beta2 "k8s.io/kube-scheduler/config/v1beta2" +) + +// 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(&v1beta2.DefaultPreemptionArgs{}, func(obj interface{}) { SetObjectDefaults_DefaultPreemptionArgs(obj.(*v1beta2.DefaultPreemptionArgs)) }) + scheme.AddTypeDefaultingFunc(&v1beta2.InterPodAffinityArgs{}, func(obj interface{}) { SetObjectDefaults_InterPodAffinityArgs(obj.(*v1beta2.InterPodAffinityArgs)) }) + scheme.AddTypeDefaultingFunc(&v1beta2.KubeSchedulerConfiguration{}, func(obj interface{}) { + SetObjectDefaults_KubeSchedulerConfiguration(obj.(*v1beta2.KubeSchedulerConfiguration)) + }) + scheme.AddTypeDefaultingFunc(&v1beta2.NodeResourcesLeastAllocatedArgs{}, func(obj interface{}) { + SetObjectDefaults_NodeResourcesLeastAllocatedArgs(obj.(*v1beta2.NodeResourcesLeastAllocatedArgs)) + }) + scheme.AddTypeDefaultingFunc(&v1beta2.NodeResourcesMostAllocatedArgs{}, func(obj interface{}) { + SetObjectDefaults_NodeResourcesMostAllocatedArgs(obj.(*v1beta2.NodeResourcesMostAllocatedArgs)) + }) + scheme.AddTypeDefaultingFunc(&v1beta2.PodTopologySpreadArgs{}, func(obj interface{}) { SetObjectDefaults_PodTopologySpreadArgs(obj.(*v1beta2.PodTopologySpreadArgs)) }) + scheme.AddTypeDefaultingFunc(&v1beta2.RequestedToCapacityRatioArgs{}, func(obj interface{}) { + SetObjectDefaults_RequestedToCapacityRatioArgs(obj.(*v1beta2.RequestedToCapacityRatioArgs)) + }) + scheme.AddTypeDefaultingFunc(&v1beta2.VolumeBindingArgs{}, func(obj interface{}) { SetObjectDefaults_VolumeBindingArgs(obj.(*v1beta2.VolumeBindingArgs)) }) + return nil +} + +func SetObjectDefaults_DefaultPreemptionArgs(in *v1beta2.DefaultPreemptionArgs) { + SetDefaults_DefaultPreemptionArgs(in) +} + +func SetObjectDefaults_InterPodAffinityArgs(in *v1beta2.InterPodAffinityArgs) { + SetDefaults_InterPodAffinityArgs(in) +} + +func SetObjectDefaults_KubeSchedulerConfiguration(in *v1beta2.KubeSchedulerConfiguration) { + SetDefaults_KubeSchedulerConfiguration(in) +} + +func SetObjectDefaults_NodeResourcesLeastAllocatedArgs(in *v1beta2.NodeResourcesLeastAllocatedArgs) { + SetDefaults_NodeResourcesLeastAllocatedArgs(in) +} + +func SetObjectDefaults_NodeResourcesMostAllocatedArgs(in *v1beta2.NodeResourcesMostAllocatedArgs) { + SetDefaults_NodeResourcesMostAllocatedArgs(in) +} + +func SetObjectDefaults_PodTopologySpreadArgs(in *v1beta2.PodTopologySpreadArgs) { + SetDefaults_PodTopologySpreadArgs(in) +} + +func SetObjectDefaults_RequestedToCapacityRatioArgs(in *v1beta2.RequestedToCapacityRatioArgs) { + SetDefaults_RequestedToCapacityRatioArgs(in) +} + +func SetObjectDefaults_VolumeBindingArgs(in *v1beta2.VolumeBindingArgs) { + SetDefaults_VolumeBindingArgs(in) +} diff --git a/pkg/scheduler/apis/config/validation/validation.go b/pkg/scheduler/apis/config/validation/validation.go index a236799cfca..64bbcc89acf 100644 --- a/pkg/scheduler/apis/config/validation/validation.go +++ b/pkg/scheduler/apis/config/validation/validation.go @@ -30,6 +30,8 @@ import ( componentbasevalidation "k8s.io/component-base/config/validation" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta1" + "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta2" ) // ValidateKubeSchedulerConfiguration ensures validation of the KubeSchedulerConfiguration struct @@ -49,7 +51,7 @@ func ValidateKubeSchedulerConfiguration(cc *config.KubeSchedulerConfiguration) u for i := range cc.Profiles { profile := &cc.Profiles[i] path := profilesPath.Index(i) - errs = append(errs, validateKubeSchedulerProfile(path, profile)...) + errs = append(errs, validateKubeSchedulerProfile(path, cc.APIVersion, profile)...) if idx, ok := existingProfiles[profile.SchedulerName]; ok { errs = append(errs, field.Duplicate(path.Child("schedulerName"), profilesPath.Index(idx).Child("schedulerName"))) } @@ -80,16 +82,61 @@ func ValidateKubeSchedulerConfiguration(cc *config.KubeSchedulerConfiguration) u return utilerrors.Flatten(utilerrors.NewAggregate(errs)) } -func validateKubeSchedulerProfile(path *field.Path, profile *config.KubeSchedulerProfile) []error { +type removedPlugins struct { + schemeGroupVersion string + plugins []string +} + +// removedPluginsByVersion maintains a list of removed plugins in each version. +// Remember to add an entry to that list when creating a new component config +// version (even if the list of removed plugins is empty). +var removedPluginsByVersion = []removedPlugins{ + { + schemeGroupVersion: v1beta1.SchemeGroupVersion.String(), + plugins: []string{}, + }, + { + schemeGroupVersion: v1beta2.SchemeGroupVersion.String(), + plugins: []string{"NodeLabel", "ServiceAffinity", "NodePreferAvoidPods"}, + }, +} + +// isPluginRemoved checks if a given plugin was removed in the given component +// config version or earlier. +func isPluginRemoved(apiVersion string, name string) (bool, string) { + for _, dp := range removedPluginsByVersion { + for _, plugin := range dp.plugins { + if name == plugin { + return true, dp.schemeGroupVersion + } + } + if apiVersion == dp.schemeGroupVersion { + break + } + } + return false, "" +} + +func validatePluginSetForRemovedPlugins(path *field.Path, apiVersion string, ps config.PluginSet) []error { + var errs []error + for i, plugin := range ps.Enabled { + if removed, removedVersion := isPluginRemoved(apiVersion, plugin.Name); removed { + errs = append(errs, field.Invalid(path.Child("enabled").Index(i), plugin.Name, fmt.Sprintf("was removed in version %q (KubeSchedulerConfiguration is version %q)", removedVersion, apiVersion))) + } + } + return errs +} + +func validateKubeSchedulerProfile(path *field.Path, apiVersion string, profile *config.KubeSchedulerProfile) []error { var errs []error if len(profile.SchedulerName) == 0 { errs = append(errs, field.Required(path.Child("schedulerName"), "")) } - errs = append(errs, validatePluginConfig(path, profile)...) + errs = append(errs, validatePluginConfig(path, apiVersion, profile)...) return errs } -func validatePluginConfig(path *field.Path, profile *config.KubeSchedulerProfile) []error { +func validatePluginConfig(path *field.Path, apiVersion string, profile *config.KubeSchedulerProfile) []error { var errs []error m := map[string]interface{}{ "DefaultPreemption": ValidateDefaultPreemptionArgs, @@ -128,6 +175,31 @@ func validatePluginConfig(path *field.Path, profile *config.KubeSchedulerProfile } } } + if profile.Plugins != nil { + pluginsPath := path.Child("plugins") + errs = append(errs, validatePluginSetForRemovedPlugins( + pluginsPath.Child("queueSort"), apiVersion, profile.Plugins.QueueSort)...) + errs = append(errs, validatePluginSetForRemovedPlugins( + pluginsPath.Child("preFilter"), apiVersion, profile.Plugins.PreFilter)...) + errs = append(errs, validatePluginSetForRemovedPlugins( + pluginsPath.Child("filter"), apiVersion, profile.Plugins.Filter)...) + errs = append(errs, validatePluginSetForRemovedPlugins( + pluginsPath.Child("postFilter"), apiVersion, profile.Plugins.PostFilter)...) + errs = append(errs, validatePluginSetForRemovedPlugins( + pluginsPath.Child("preScore"), apiVersion, profile.Plugins.PreScore)...) + errs = append(errs, validatePluginSetForRemovedPlugins( + pluginsPath.Child("score"), apiVersion, profile.Plugins.Score)...) + errs = append(errs, validatePluginSetForRemovedPlugins( + pluginsPath.Child("reserve"), apiVersion, profile.Plugins.Reserve)...) + errs = append(errs, validatePluginSetForRemovedPlugins( + pluginsPath.Child("permit"), apiVersion, profile.Plugins.Permit)...) + errs = append(errs, validatePluginSetForRemovedPlugins( + pluginsPath.Child("preBind"), apiVersion, profile.Plugins.PreBind)...) + errs = append(errs, validatePluginSetForRemovedPlugins( + pluginsPath.Child("bind"), apiVersion, profile.Plugins.Bind)...) + errs = append(errs, validatePluginSetForRemovedPlugins( + pluginsPath.Child("postBind"), apiVersion, profile.Plugins.PostBind)...) + } return errs } diff --git a/pkg/scheduler/apis/config/validation/validation_test.go b/pkg/scheduler/apis/config/validation/validation_test.go index c241a3b7ce3..e24ca350af4 100644 --- a/pkg/scheduler/apis/config/validation/validation_test.go +++ b/pkg/scheduler/apis/config/validation/validation_test.go @@ -25,12 +25,17 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" componentbaseconfig "k8s.io/component-base/config" "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta1" + "k8s.io/kubernetes/pkg/scheduler/apis/config/v1beta2" ) func TestValidateKubeSchedulerConfiguration(t *testing.T) { podInitialBackoffSeconds := int64(1) podMaxBackoffSeconds := int64(1) validConfig := &config.KubeSchedulerConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta2.SchemeGroupVersion.String(), + }, Parallelism: 8, HealthzBindAddress: "0.0.0.0:10254", MetricsBindAddress: "0.0.0.0:10254", @@ -113,12 +118,18 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) { metricsBindAddrPortInvalid := validConfig.DeepCopy() metricsBindAddrPortInvalid.MetricsBindAddress = "0.0.0.0:909090" + metricsBindAddrHostOnlyInvalid := validConfig.DeepCopy() + metricsBindAddrHostOnlyInvalid.MetricsBindAddress = "999.999.999.999" + healthzBindAddrHostInvalid := validConfig.DeepCopy() healthzBindAddrHostInvalid.HealthzBindAddress = "0.0.0.0.0:9090" healthzBindAddrPortInvalid := validConfig.DeepCopy() healthzBindAddrPortInvalid.HealthzBindAddress = "0.0.0.0:909090" + healthzBindAddrHostOnlyInvalid := validConfig.DeepCopy() + healthzBindAddrHostOnlyInvalid.HealthzBindAddress = "999.999.999.999" + enableContentProfilingSetWithoutEnableProfiling := validConfig.DeepCopy() enableContentProfilingSetWithoutEnableProfiling.EnableProfiling = false enableContentProfilingSetWithoutEnableProfiling.EnableContentionProfiling = true @@ -210,6 +221,20 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) { BindVerb: "bar", }) + badRemovedPlugins1 := validConfig.DeepCopy() // defalt v1beta2 + 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}) + + goodRemovedPlugins1 := validConfig.DeepCopy() // ServiceAffinity is okay in v1beta1. + goodRemovedPlugins1.APIVersion = v1beta1.SchemeGroupVersion.String() + goodRemovedPlugins1.Profiles[0].Plugins.Score.Enabled = append(goodRemovedPlugins1.Profiles[0].Plugins.Score.Enabled, config.Plugin{Name: "ServiceAffinity", Weight: 2}) + + goodRemovedPlugins2 := validConfig.DeepCopy() + goodRemovedPlugins2.Profiles[0].Plugins.Score.Enabled = append(goodRemovedPlugins2.Profiles[0].Plugins.Score.Enabled, config.Plugin{Name: "PodTopologySpread", Weight: 2}) + scenarios := map[string]struct { expectedToFail bool config *config.KubeSchedulerConfiguration @@ -238,6 +263,10 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) { expectedToFail: true, config: healthzBindAddrHostInvalid, }, + "bad-healthz-host-only-invalid": { + expectedToFail: true, + config: healthzBindAddrHostOnlyInvalid, + }, "bad-metrics-port-invalid": { expectedToFail: true, config: metricsBindAddrPortInvalid, @@ -246,6 +275,10 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) { expectedToFail: true, config: metricsBindAddrHostInvalid, }, + "bad-metrics-host-only-invalid": { + expectedToFail: true, + config: metricsBindAddrHostOnlyInvalid, + }, "bad-percentage-of-nodes-to-score": { expectedToFail: true, config: percentageOfNodesToScore101, @@ -294,6 +327,22 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) { expectedToFail: true, config: mismatchQueueSort, }, + "bad-removed-plugins-1": { + expectedToFail: true, + config: badRemovedPlugins1, + }, + "bad-removed-plugins-2": { + expectedToFail: true, + config: badRemovedPlugins2, + }, + "good-removed-plugins-1": { + expectedToFail: false, + config: goodRemovedPlugins1, + }, + "good-removed-plugins-2": { + expectedToFail: false, + config: goodRemovedPlugins2, + }, } for name, scenario := range scenarios { diff --git a/pkg/scheduler/factory.go b/pkg/scheduler/factory.go index 6bc62fa718a..232496883fb 100644 --- a/pkg/scheduler/factory.go +++ b/pkg/scheduler/factory.go @@ -70,6 +70,8 @@ type Configurator struct { schedulerCache internalcache.Cache + componentConfigVersion string + // Always check all predicates even if the middle of one predicate fails. alwaysCheckAllPredicates bool @@ -138,6 +140,7 @@ func (c *Configurator) create() (*Scheduler, error) { // The nominator will be passed all the way to framework instantiation. nominator := internalqueue.NewSafePodNominator(c.informerFactory.Core().V1().Pods().Lister()) profiles, err := profile.NewMap(c.profiles, c.registry, c.recorderFactory, + frameworkruntime.WithComponentConfigVersion(c.componentConfigVersion), frameworkruntime.WithClientSet(c.client), frameworkruntime.WithKubeConfig(c.kubeConfig), frameworkruntime.WithInformerFactory(c.informerFactory), diff --git a/pkg/scheduler/framework/plugins/nodelabel/node_label.go b/pkg/scheduler/framework/plugins/nodelabel/node_label.go index c16ca5574be..c6281f6c95e 100644 --- a/pkg/scheduler/framework/plugins/nodelabel/node_label.go +++ b/pkg/scheduler/framework/plugins/nodelabel/node_label.go @@ -14,6 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ +// This plugin has been deprecated and is only configurable through the +// scheduler policy API and the v1beta1 component config API. It is recommended +// to use the NodeAffinity plugin instead. package nodelabel import ( @@ -23,6 +26,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/klog/v2" "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config/validation" "k8s.io/kubernetes/pkg/scheduler/framework" @@ -46,6 +50,7 @@ func New(plArgs runtime.Object, handle framework.Handle) (framework.Plugin, erro return nil, err } + klog.Warning("NodeLabel plugin is deprecated and will be removed in a future version; use NodeAffinity instead") return &NodeLabel{ handle: handle, args: args, diff --git a/pkg/scheduler/framework/plugins/nodepreferavoidpods/node_prefer_avoid_pods.go b/pkg/scheduler/framework/plugins/nodepreferavoidpods/node_prefer_avoid_pods.go index 169284a7f05..625d286ed73 100644 --- a/pkg/scheduler/framework/plugins/nodepreferavoidpods/node_prefer_avoid_pods.go +++ b/pkg/scheduler/framework/plugins/nodepreferavoidpods/node_prefer_avoid_pods.go @@ -14,6 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ +// This plugin has been deprecated and is only configurable through the +// scheduler policy API and the v1beta1 component config API. It is recommended +// to use node taints instead. package nodepreferavoidpods import ( @@ -24,6 +27,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" v1helper "k8s.io/component-helpers/scheduling/corev1" + "k8s.io/klog/v2" "k8s.io/kubernetes/pkg/scheduler/framework" ) @@ -85,5 +89,6 @@ func (pl *NodePreferAvoidPods) ScoreExtensions() framework.ScoreExtensions { // New initializes a new plugin and returns it. func New(_ runtime.Object, h framework.Handle) (framework.Plugin, error) { + klog.Warning("NodePreferAvoidPods plugin is deprecated and will be removed in a future version; use node taints instead") return &NodePreferAvoidPods{handle: h}, nil } diff --git a/pkg/scheduler/framework/plugins/serviceaffinity/service_affinity.go b/pkg/scheduler/framework/plugins/serviceaffinity/service_affinity.go index 35a2e103f24..3b6cc5d31b1 100644 --- a/pkg/scheduler/framework/plugins/serviceaffinity/service_affinity.go +++ b/pkg/scheduler/framework/plugins/serviceaffinity/service_affinity.go @@ -14,6 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ +// This plugin has been deprecated and is only configurable through the +// scheduler policy API and the v1beta1 component config API. It is recommended +// to use the InterPodAffinity plugin instead. package serviceaffinity import ( @@ -24,6 +27,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" corelisters "k8s.io/client-go/listers/core/v1" + "k8s.io/klog/v2" "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/helper" @@ -70,6 +74,7 @@ func New(plArgs runtime.Object, handle framework.Handle) (framework.Plugin, erro } serviceLister := handle.SharedInformerFactory().Core().V1().Services().Lister() + klog.Warning("ServiceAffinity plugin is deprecated and will be removed in a future version; use InterPodAffinity instead") return &ServiceAffinity{ sharedLister: handle.SnapshotSharedLister(), serviceLister: serviceLister, diff --git a/pkg/scheduler/framework/runtime/framework.go b/pkg/scheduler/framework/runtime/framework.go index ed763381cec..162e2187cc5 100644 --- a/pkg/scheduler/framework/runtime/framework.go +++ b/pkg/scheduler/framework/runtime/framework.go @@ -25,6 +25,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/informers" @@ -34,6 +35,7 @@ import ( "k8s.io/component-helpers/scheduling/corev1" "k8s.io/klog/v2" "k8s.io/kube-scheduler/config/v1beta1" + "k8s.io/kube-scheduler/config/v1beta2" "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" "k8s.io/kubernetes/pkg/scheduler/framework" @@ -142,23 +144,34 @@ func (f *frameworkImpl) Extenders() []framework.Extender { } type frameworkOptions struct { - clientSet clientset.Interface - kubeConfig *restclient.Config - eventRecorder events.EventRecorder - informerFactory informers.SharedInformerFactory - snapshotSharedLister framework.SharedLister - metricsRecorder *metricsRecorder - podNominator framework.PodNominator - extenders []framework.Extender - runAllFilters bool - captureProfile CaptureProfile - clusterEventMap map[framework.ClusterEvent]sets.String - parallelizer parallelize.Parallelizer + componentConfigVersion string + clientSet clientset.Interface + kubeConfig *restclient.Config + eventRecorder events.EventRecorder + informerFactory informers.SharedInformerFactory + snapshotSharedLister framework.SharedLister + metricsRecorder *metricsRecorder + podNominator framework.PodNominator + extenders []framework.Extender + runAllFilters bool + captureProfile CaptureProfile + clusterEventMap map[framework.ClusterEvent]sets.String + parallelizer parallelize.Parallelizer } // Option for the frameworkImpl. type Option func(*frameworkOptions) +// WithComponentConfigVersion sets the component config version to the +// KubeSchedulerConfiguration version used. The string should be the full +// scheme group/version of the external type we converted from (for example +// "kubescheduler.config.k8s.io/v1beta2") +func WithComponentConfigVersion(componentConfigVersion string) Option { + return func(o *frameworkOptions) { + o.componentConfigVersion = componentConfigVersion + } +} + // WithClientSet sets clientSet for the scheduling frameworkImpl. func WithClientSet(clientSet clientset.Interface) Option { return func(o *frameworkOptions) { @@ -322,7 +335,7 @@ func NewFramework(r Registry, profile *config.KubeSchedulerProfile, opts ...Opti continue } - args, err := getPluginArgsOrDefault(pluginConfig, name) + args, err := getPluginArgsOrDefault(options.componentConfigVersion, pluginConfig, name) if err != nil { return nil, fmt.Errorf("getting args for Plugin %q: %w", name, err) } @@ -415,13 +428,22 @@ func registerClusterEvents(name string, eventToPlugins map[framework.ClusterEven // a default from the scheme. Returns `nil, nil` if the plugin does not have a // defined arg types, such as in-tree plugins that don't require configuration // or out-of-tree plugins. -func getPluginArgsOrDefault(pluginConfig map[string]runtime.Object, name string) (runtime.Object, error) { +func getPluginArgsOrDefault(componentConfigVersion string, pluginConfig map[string]runtime.Object, name string) (runtime.Object, error) { res, ok := pluginConfig[name] if ok { return res, nil } // Use defaults from latest config API version. - gvk := v1beta1.SchemeGroupVersion.WithKind(name + "Args") + var gvk schema.GroupVersionKind + switch componentConfigVersion { + case v1beta1.SchemeGroupVersion.String(): + gvk = v1beta1.SchemeGroupVersion.WithKind(name + "Args") + case v1beta2.SchemeGroupVersion.String(): + gvk = v1beta2.SchemeGroupVersion.WithKind(name + "Args") + default: + // default to v1beta2 (latest API) + gvk = v1beta2.SchemeGroupVersion.WithKind(name + "Args") + } obj, _, err := configDecoder.Decode(nil, &gvk, nil) if runtime.IsNotRegisteredError(err) { // This plugin is out-of-tree or doesn't require configuration. diff --git a/pkg/scheduler/framework/runtime/framework_test.go b/pkg/scheduler/framework/runtime/framework_test.go index b1f9bc87aa1..9083a6f1d7c 100644 --- a/pkg/scheduler/framework/runtime/framework_test.go +++ b/pkg/scheduler/framework/runtime/framework_test.go @@ -546,7 +546,7 @@ func TestNewFrameworkPluginDefaults(t *testing.T) { "InterPodAffinity": &config.InterPodAffinityArgs{ HardPodAffinityWeight: 1, }, - "NodeLabel": &config.NodeLabelArgs{}, + "NodeLabel": nil, "NodeResourcesFit": &config.NodeResourcesFitArgs{}, "NodeResourcesLeastAllocated": &config.NodeResourcesLeastAllocatedArgs{ Resources: []config.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}, @@ -609,7 +609,7 @@ func TestNewFrameworkPluginDefaults(t *testing.T) { "InterPodAffinity": &config.InterPodAffinityArgs{ HardPodAffinityWeight: 3, }, - "NodeLabel": &config.NodeLabelArgs{}, + "NodeLabel": nil, "NodeResourcesFit": &config.NodeResourcesFitArgs{ IgnoredResources: []string{"example.com/foo"}, }, diff --git a/pkg/scheduler/scheduler.go b/pkg/scheduler/scheduler.go index 8d4d734c731..2e107355080 100644 --- a/pkg/scheduler/scheduler.go +++ b/pkg/scheduler/scheduler.go @@ -94,6 +94,7 @@ type Scheduler struct { } type schedulerOptions struct { + componentConfigVersion string kubeConfig *restclient.Config schedulerAlgorithmSource schedulerapi.SchedulerAlgorithmSource percentageOfNodesToScore int32 @@ -110,6 +111,16 @@ type schedulerOptions struct { // Option configures a Scheduler type Option func(*schedulerOptions) +// WithComponentConfigVersion sets the component config version to the +// KubeSchedulerConfiguration version used. The string should be the full +// scheme group/version of the external type we converted from (for example +// "kubescheduler.config.k8s.io/v1beta2") +func WithComponentConfigVersion(apiVersion string) Option { + return func(o *schedulerOptions) { + o.componentConfigVersion = apiVersion + } +} + // WithKubeConfig sets the kube config for Scheduler. func WithKubeConfig(cfg *restclient.Config) Option { return func(o *schedulerOptions) { @@ -227,6 +238,7 @@ func New(client clientset.Interface, clusterEventMap := make(map[framework.ClusterEvent]sets.String) configurator := &Configurator{ + componentConfigVersion: options.componentConfigVersion, client: client, kubeConfig: options.kubeConfig, recorderFactory: recorderFactory, diff --git a/staging/src/k8s.io/kube-scheduler/config/v1beta1/types_pluginargs.go b/staging/src/k8s.io/kube-scheduler/config/v1beta1/types_pluginargs.go index 22d9dbb2b36..61408d196b5 100644 --- a/staging/src/k8s.io/kube-scheduler/config/v1beta1/types_pluginargs.go +++ b/staging/src/k8s.io/kube-scheduler/config/v1beta1/types_pluginargs.go @@ -57,6 +57,10 @@ type InterPodAffinityArgs struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // NodeLabelArgs holds arguments used to configure the NodeLabel plugin. +// +// This plugin has been deprecated and is only configurable through the +// scheduler policy API and the v1beta1 component config API. It is recommended +// to use the NodeAffinity plugin instead. type NodeLabelArgs struct { metav1.TypeMeta `json:",inline"` @@ -191,6 +195,10 @@ type ResourceSpec struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // ServiceAffinityArgs holds arguments used to configure the ServiceAffinity plugin. +// +// This plugin has been deprecated and is only configurable through the +// scheduler policy API and the v1beta1 component config API. It is recommended +// to use the InterPodAffinity plugin instead. type ServiceAffinityArgs struct { metav1.TypeMeta `json:",inline"` diff --git a/staging/src/k8s.io/kube-scheduler/config/v1beta2/doc.go b/staging/src/k8s.io/kube-scheduler/config/v1beta2/doc.go new file mode 100644 index 00000000000..c9f5f62ed8e --- /dev/null +++ b/staging/src/k8s.io/kube-scheduler/config/v1beta2/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 v1beta2 // import "k8s.io/kube-scheduler/config/v1beta2" diff --git a/staging/src/k8s.io/kube-scheduler/config/v1beta2/register.go b/staging/src/k8s.io/kube-scheduler/config/v1beta2/register.go new file mode 100644 index 00000000000..7c13a31dbad --- /dev/null +++ b/staging/src/k8s.io/kube-scheduler/config/v1beta2/register.go @@ -0,0 +1,52 @@ +/* +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 v1beta2 + +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: "v1beta2"} + +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{}, + &NodeResourcesFitArgs{}, + &PodTopologySpreadArgs{}, + &RequestedToCapacityRatioArgs{}, + &NodeResourcesLeastAllocatedArgs{}, + &NodeResourcesMostAllocatedArgs{}, + &VolumeBindingArgs{}, + &NodeAffinityArgs{}, + ) + return nil +} diff --git a/staging/src/k8s.io/kube-scheduler/config/v1beta2/types.go b/staging/src/k8s.io/kube-scheduler/config/v1beta2/types.go new file mode 100644 index 00000000000..bb9f217960a --- /dev/null +++ b/staging/src/k8s.io/kube-scheduler/config/v1beta2/types.go @@ -0,0 +1,309 @@ +/* +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 v1beta2 + +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"` + // HealthzBindAddress is the IP address and port for the health check server to serve on, + // defaulting to 0.0.0.0:10251 + HealthzBindAddress *string `json:"healthzBindAddress,omitempty"` + // MetricsBindAddress is the IP address and port for the metrics server to + // serve on, defaulting to 0.0.0.0:10251. + MetricsBindAddress *string `json:"metricsBindAddress,omitempty"` + + // 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. + // 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/v1beta2/types_pluginargs.go b/staging/src/k8s.io/kube-scheduler/config/v1beta2/types_pluginargs.go new file mode 100644 index 00000000000..7372cbcaa32 --- /dev/null +++ b/staging/src/k8s.io/kube-scheduler/config/v1beta2/types_pluginargs.go @@ -0,0 +1,197 @@ +/* +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 v1beta2 + +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. + // +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 '/'. + // +listType=atomic + IgnoredResourceGroups []string `json:"ignoredResourceGroups,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 + +// RequestedToCapacityRatioArgs holds arguments used to configure RequestedToCapacityRatio plugin. +type RequestedToCapacityRatioArgs struct { + metav1.TypeMeta `json:",inline"` + + // Points defining priority function shape + // +listType=atomic + Shape []UtilizationShapePoint `json:"shape"` + // Resources to be managed + // +listType=atomic + Resources []ResourceSpec `json:"resources,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// NodeResourcesLeastAllocatedArgs holds arguments used to configure NodeResourcesLeastAllocated plugin. +type NodeResourcesLeastAllocatedArgs struct { + metav1.TypeMeta `json:",inline"` + + // Resources to be managed, if no resource is provided, default resource set with both + // the weight of "cpu" and "memory" set to "1" will be applied. + // Resource with "0" weight will not accountable for the final score. + // +listType=atomic + Resources []ResourceSpec `json:"resources,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// NodeResourcesMostAllocatedArgs holds arguments used to configure NodeResourcesMostAllocated plugin. +type NodeResourcesMostAllocatedArgs struct { + metav1.TypeMeta `json:",inline"` + + // Resources to be managed, if no resource is provided, default resource set with both + // the weight of "cpu" and "memory" set to "1" will be applied. + // Resource with "0" weight will not accountable for the final score. + // +listType=atomic + 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 single resource and weight for bin packing of priority RequestedToCapacityRatioArguments. +type ResourceSpec struct { + // Name of the resource to be managed by RequestedToCapacityRatio function. + 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"` +} + +// +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"` +} diff --git a/staging/src/k8s.io/kube-scheduler/config/v1beta2/zz_generated.deepcopy.go b/staging/src/k8s.io/kube-scheduler/config/v1beta2/zz_generated.deepcopy.go new file mode 100644 index 00000000000..e7cb4e7b3e9 --- /dev/null +++ b/staging/src/k8s.io/kube-scheduler/config/v1beta2/zz_generated.deepcopy.go @@ -0,0 +1,573 @@ +// +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 v1beta2 + +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 + if in.HealthzBindAddress != nil { + in, out := &in.HealthzBindAddress, &out.HealthzBindAddress + *out = new(string) + **out = **in + } + if in.MetricsBindAddress != nil { + in, out := &in.MetricsBindAddress, &out.MetricsBindAddress + *out = new(string) + **out = **in + } + 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 *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) + } + 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 *NodeResourcesLeastAllocatedArgs) DeepCopyInto(out *NodeResourcesLeastAllocatedArgs) { + *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 NodeResourcesLeastAllocatedArgs. +func (in *NodeResourcesLeastAllocatedArgs) DeepCopy() *NodeResourcesLeastAllocatedArgs { + if in == nil { + return nil + } + out := new(NodeResourcesLeastAllocatedArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeResourcesLeastAllocatedArgs) 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 *NodeResourcesMostAllocatedArgs) DeepCopyInto(out *NodeResourcesMostAllocatedArgs) { + *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 NodeResourcesMostAllocatedArgs. +func (in *NodeResourcesMostAllocatedArgs) DeepCopy() *NodeResourcesMostAllocatedArgs { + if in == nil { + return nil + } + out := new(NodeResourcesMostAllocatedArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeResourcesMostAllocatedArgs) 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 *RequestedToCapacityRatioArgs) DeepCopyInto(out *RequestedToCapacityRatioArgs) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.Shape != nil { + in, out := &in.Shape, &out.Shape + *out = make([]UtilizationShapePoint, len(*in)) + copy(*out, *in) + } + 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 RequestedToCapacityRatioArgs. +func (in *RequestedToCapacityRatioArgs) DeepCopy() *RequestedToCapacityRatioArgs { + if in == nil { + return nil + } + out := new(RequestedToCapacityRatioArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RequestedToCapacityRatioArgs) 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 *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 *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 + } + 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 +} diff --git a/vendor/modules.txt b/vendor/modules.txt index d11e556e772..c19ca439ac9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1992,6 +1992,7 @@ k8s.io/kube-proxy/config/v1alpha1 ## explicit k8s.io/kube-scheduler/config/v1 k8s.io/kube-scheduler/config/v1beta1 +k8s.io/kube-scheduler/config/v1beta2 k8s.io/kube-scheduler/extender/v1 # k8s.io/kubectl v0.0.0 => ./staging/src/k8s.io/kubectl ## explicit