diff --git a/pkg/api/serialization_test.go b/pkg/api/serialization_test.go index e2660cfb1b0..89c08f3fa82 100644 --- a/pkg/api/serialization_test.go +++ b/pkg/api/serialization_test.go @@ -366,6 +366,7 @@ func TestEncodePtr(t *testing.T) { TerminationGracePeriodSeconds: &grace, SecurityContext: &api.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, } obj := runtime.Object(pod) diff --git a/pkg/api/testing/fuzzer.go b/pkg/api/testing/fuzzer.go index d32473b07ed..9af9664990e 100644 --- a/pkg/api/testing/fuzzer.go +++ b/pkg/api/testing/fuzzer.go @@ -134,6 +134,9 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz if s.Affinity == nil { s.Affinity = new(api.Affinity) } + if s.SchedulerName == "" { + s.SchedulerName = api.DefaultSchedulerName + } }, func(j *api.PodPhase, c fuzz.Continue) { statuses := []api.PodPhase{api.PodPending, api.PodRunning, api.PodFailed, api.PodUnknown} diff --git a/pkg/api/testing/pod_specs.go b/pkg/api/testing/pod_specs.go index 87300a3da73..eb7c4e06b73 100644 --- a/pkg/api/testing/pod_specs.go +++ b/pkg/api/testing/pod_specs.go @@ -29,6 +29,7 @@ func DeepEqualSafePodSpec() api.PodSpec { DNSPolicy: api.DNSClusterFirst, TerminationGracePeriodSeconds: &grace, SecurityContext: &api.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, } } diff --git a/pkg/api/types.go b/pkg/api/types.go index eb8c0631d83..fdf04938f60 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -1856,6 +1856,10 @@ type PodSpec struct { // If specified, the pod's scheduling constraints // +optional Affinity *Affinity + // If specified, the pod will be dispatched by specified scheduler. + // If not specified, the pod will be dispatched by default scheduler. + // +optional + SchedulerName string } // Sysctl defines a kernel parameter to be set diff --git a/pkg/api/v1/defaults.go b/pkg/api/v1/defaults.go index 50950837721..e6de1be9d8e 100644 --- a/pkg/api/v1/defaults.go +++ b/pkg/api/v1/defaults.go @@ -174,6 +174,9 @@ func SetDefaults_PodSpec(obj *PodSpec) { period := int64(DefaultTerminationGracePeriodSeconds) obj.TerminationGracePeriodSeconds = &period } + if obj.SchedulerName == "" { + obj.SchedulerName = DefaultSchedulerName + } } func SetDefaults_Probe(obj *Probe) { if obj.TimeoutSeconds == 0 { diff --git a/pkg/api/v1/defaults_test.go b/pkg/api/v1/defaults_test.go index 7d7b92cf686..61d7ac467aa 100644 --- a/pkg/api/v1/defaults_test.go +++ b/pkg/api/v1/defaults_test.go @@ -807,3 +807,12 @@ func TestSetDefaultProbe(t *testing.T) { t.Errorf("Expected probe: %+v\ngot: %+v\n", expectedProbe, actualProbe) } } + +func TestSetDefaultSchedulerName(t *testing.T) { + pod := &v1.Pod{} + + output := roundTrip(t, runtime.Object(pod)).(*v1.Pod) + if output.Spec.SchedulerName != v1.DefaultSchedulerName { + t.Errorf("Expected scheduler name: %+v\ngot: %+v\n", v1.DefaultSchedulerName, output.Spec.SchedulerName) + } +} diff --git a/pkg/api/v1/types.go b/pkg/api/v1/types.go index a43f63c24c6..e3388f0f3eb 100644 --- a/pkg/api/v1/types.go +++ b/pkg/api/v1/types.go @@ -2140,6 +2140,10 @@ type PodSpec struct { // If specified, the pod's scheduling constraints // +optional Affinity *Affinity `json:"affinity,omitempty" protobuf:"bytes,18,opt,name=affinity"` + // If specified, the pod will be dispatched by specified scheduler. + // If not specified, the pod will be dispatched by default scheduler. + // +optional + SchedulerName string `json:"schedulername,omitempty" protobuf:"bytes,19,opt,name=schedulername"` } // PodSecurityContext holds pod-level security attributes and common container settings. diff --git a/pkg/apis/componentconfig/types.go b/pkg/apis/componentconfig/types.go index b5a52bb1894..bd4d30b0da6 100644 --- a/pkg/apis/componentconfig/types.go +++ b/pkg/apis/componentconfig/types.go @@ -561,8 +561,7 @@ type KubeSchedulerConfiguration struct { // kubeAPIBurst is the QPS burst to use while talking with kubernetes apiserver. KubeAPIBurst int32 // schedulerName is name of the scheduler, used to select which pods - // will be processed by this scheduler, based on pod's annotation with - // key 'scheduler.alpha.kubernetes.io/name'. + // will be processed by this scheduler, based on pod's "spec.SchedulerName". SchedulerName string // RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule // corresponding to every RequiredDuringScheduling affinity rule. diff --git a/pkg/apis/componentconfig/v1alpha1/types.go b/pkg/apis/componentconfig/v1alpha1/types.go index 759194361dc..f8f5e181a02 100644 --- a/pkg/apis/componentconfig/v1alpha1/types.go +++ b/pkg/apis/componentconfig/v1alpha1/types.go @@ -122,8 +122,7 @@ type KubeSchedulerConfiguration struct { // kubeAPIBurst is the QPS burst to use while talking with kubernetes apiserver. KubeAPIBurst int `json:"kubeAPIBurst"` // schedulerName is name of the scheduler, used to select which pods - // will be processed by this scheduler, based on pod's annotation with - // key 'scheduler.alpha.kubernetes.io/name'. + // will be processed by this scheduler, based on pod's "spec.SchedulerName". SchedulerName string `json:"schedulerName"` // RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule // corresponding to every RequiredDuringScheduling affinity rule. diff --git a/pkg/apis/extensions/v1beta1/defaults_test.go b/pkg/apis/extensions/v1beta1/defaults_test.go index 33119c13f33..c88805151c3 100644 --- a/pkg/apis/extensions/v1beta1/defaults_test.go +++ b/pkg/apis/extensions/v1beta1/defaults_test.go @@ -40,6 +40,7 @@ func TestSetDefaultDaemonSet(t *testing.T) { RestartPolicy: v1.RestartPolicyAlways, SecurityContext: &v1.PodSecurityContext{}, TerminationGracePeriodSeconds: &period, + SchedulerName: api.DefaultSchedulerName, }, ObjectMeta: metav1.ObjectMeta{ Labels: defaultLabels, @@ -51,6 +52,7 @@ func TestSetDefaultDaemonSet(t *testing.T) { RestartPolicy: v1.RestartPolicyAlways, SecurityContext: &v1.PodSecurityContext{}, TerminationGracePeriodSeconds: &period, + SchedulerName: api.DefaultSchedulerName, }, } tests := []struct { @@ -155,6 +157,7 @@ func TestSetDefaultDeployment(t *testing.T) { RestartPolicy: v1.RestartPolicyAlways, SecurityContext: &v1.PodSecurityContext{}, TerminationGracePeriodSeconds: &period, + SchedulerName: api.DefaultSchedulerName, }, } tests := []struct { diff --git a/pkg/kubectl/cmd/util/helpers_test.go b/pkg/kubectl/cmd/util/helpers_test.go index 7abb9ac8377..d8dae77f849 100644 --- a/pkg/kubectl/cmd/util/helpers_test.go +++ b/pkg/kubectl/cmd/util/helpers_test.go @@ -131,6 +131,7 @@ func TestMerge(t *testing.T) { DNSPolicy: api.DNSClusterFirst, TerminationGracePeriodSeconds: &grace, SecurityContext: &api.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, }, }, diff --git a/pkg/kubelet/config/common_test.go b/pkg/kubelet/config/common_test.go index 455b113339b..18556b1517d 100644 --- a/pkg/kubelet/config/common_test.go +++ b/pkg/kubelet/config/common_test.go @@ -53,6 +53,7 @@ func TestDecodeSinglePod(t *testing.T) { SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), }}, SecurityContext: &v1.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, } json, err := runtime.Encode(testapi.Default.Codec(), pod) @@ -113,6 +114,7 @@ func TestDecodePodList(t *testing.T) { SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), }}, SecurityContext: &v1.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, } podList := &v1.PodList{ diff --git a/pkg/kubelet/config/file_linux_test.go b/pkg/kubelet/config/file_linux_test.go index bd96997e1b0..d009857b7b5 100644 --- a/pkg/kubelet/config/file_linux_test.go +++ b/pkg/kubelet/config/file_linux_test.go @@ -188,6 +188,7 @@ func getTestCases(hostname types.NodeName) []*testCase { Spec: v1.PodSpec{ Containers: []v1.Container{{Name: "image", Image: "test/image", SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults()}}, SecurityContext: &v1.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, Status: v1.PodStatus{ Phase: v1.PodPending, @@ -213,6 +214,7 @@ func getTestCases(hostname types.NodeName) []*testCase { ImagePullPolicy: "Always", SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults()}}, SecurityContext: &v1.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, Status: v1.PodStatus{ Phase: v1.PodPending, diff --git a/pkg/kubelet/config/http_test.go b/pkg/kubelet/config/http_test.go index 2b2f0453937..ada382f35b0 100644 --- a/pkg/kubelet/config/http_test.go +++ b/pkg/kubelet/config/http_test.go @@ -147,6 +147,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { NodeName: string(nodeName), Containers: []v1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1.PullAlways}}, SecurityContext: &v1.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, Status: v1.PodStatus{ Phase: v1.PodPending, @@ -168,6 +169,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { DNSPolicy: v1.DNSClusterFirst, SecurityContext: &v1.PodSecurityContext{}, TerminationGracePeriodSeconds: &grace, + SchedulerName: api.DefaultSchedulerName, Containers: []v1.Container{{ Name: "1", @@ -198,6 +200,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { NodeName: nodeName, Containers: []v1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1.PullAlways}}, SecurityContext: &v1.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, Status: v1.PodStatus{ Phase: v1.PodPending, @@ -212,6 +215,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { NodeName: nodeName, Containers: []v1.Container{{Name: "2", Image: "bar:bartag", ImagePullPolicy: ""}}, SecurityContext: &v1.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, Status: v1.PodStatus{ Phase: v1.PodPending, @@ -235,6 +239,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { DNSPolicy: v1.DNSClusterFirst, TerminationGracePeriodSeconds: &grace, SecurityContext: &v1.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, Containers: []v1.Container{{ Name: "1", @@ -261,6 +266,7 @@ func TestExtractPodsFromHTTP(t *testing.T) { DNSPolicy: v1.DNSClusterFirst, TerminationGracePeriodSeconds: &grace, SecurityContext: &v1.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, Containers: []v1.Container{{ Name: "2", diff --git a/pkg/registry/core/pod/storage/storage_test.go b/pkg/registry/core/pod/storage/storage_test.go index 8e68929f21b..eeee5a15309 100644 --- a/pkg/registry/core/pod/storage/storage_test.go +++ b/pkg/registry/core/pod/storage/storage_test.go @@ -73,6 +73,7 @@ func validNewPod() *api.Pod { }, }, SecurityContext: &api.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, } } @@ -659,6 +660,7 @@ func TestEtcdUpdateScheduled(t *testing.T) { }, }, SecurityContext: &api.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, }, nil, 1) if err != nil { @@ -687,6 +689,7 @@ func TestEtcdUpdateScheduled(t *testing.T) { TerminationGracePeriodSeconds: &grace, SecurityContext: &api.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, } _, _, err = storage.Update(ctx, podIn.Name, rest.DefaultUpdatedObjectInfo(&podIn, api.Scheme)) @@ -727,6 +730,7 @@ func TestEtcdUpdateStatus(t *testing.T) { }, }, SecurityContext: &api.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, } err := storage.Storage.Create(ctx, key, &podStart, nil, 0) @@ -751,6 +755,7 @@ func TestEtcdUpdateStatus(t *testing.T) { }, }, SecurityContext: &api.PodSecurityContext{}, + SchedulerName: api.DefaultSchedulerName, }, Status: api.PodStatus{ Phase: api.PodRunning, diff --git a/plugin/cmd/kube-scheduler/app/options/options.go b/plugin/cmd/kube-scheduler/app/options/options.go index 4b599c7a633..840bed0c85a 100644 --- a/plugin/cmd/kube-scheduler/app/options/options.go +++ b/plugin/cmd/kube-scheduler/app/options/options.go @@ -66,7 +66,7 @@ func (s *SchedulerServer) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&s.ContentType, "kube-api-content-type", s.ContentType, "Content type of requests sent to apiserver.") fs.Float32Var(&s.KubeAPIQPS, "kube-api-qps", s.KubeAPIQPS, "QPS to use while talking with kubernetes apiserver") fs.Int32Var(&s.KubeAPIBurst, "kube-api-burst", s.KubeAPIBurst, "Burst to use while talking with kubernetes apiserver") - fs.StringVar(&s.SchedulerName, "scheduler-name", s.SchedulerName, "Name of the scheduler, used to select which pods will be processed by this scheduler, based on pod's annotation with key 'scheduler.alpha.kubernetes.io/name'") + fs.StringVar(&s.SchedulerName, "scheduler-name", s.SchedulerName, "Name of the scheduler, used to select which pods will be processed by this scheduler, based on pod's \"spec.SchedulerName\".") fs.IntVar(&s.HardPodAffinitySymmetricWeight, "hard-pod-affinity-symmetric-weight", api.DefaultHardPodAffinitySymmetricWeight, "RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule corresponding "+ "to every RequiredDuringScheduling affinity rule. --hard-pod-affinity-symmetric-weight represents the weight of implicit PreferredDuringScheduling affinity rule.") diff --git a/plugin/pkg/scheduler/factory/factory.go b/plugin/pkg/scheduler/factory/factory.go index 1fc40ef411b..1d94ee5ba1e 100644 --- a/plugin/pkg/scheduler/factory/factory.go +++ b/plugin/pkg/scheduler/factory/factory.go @@ -48,9 +48,8 @@ import ( ) const ( - SchedulerAnnotationKey = "scheduler.alpha.kubernetes.io/name" - initialGetBackoff = 100 * time.Millisecond - maximalGetBackoff = time.Minute + initialGetBackoff = 100 * time.Millisecond + maximalGetBackoff = time.Minute ) // ConfigFactory is the default implementation of the scheduler.Configurator interface. @@ -90,8 +89,7 @@ type ConfigFactory struct { schedulerCache schedulercache.Cache // SchedulerName of a scheduler is used to select which pods will be - // processed by this scheduler, based on pods's annotation key: - // 'scheduler.alpha.kubernetes.io/name' + // processed by this scheduler, based on pods's "spec.SchedulerName". schedulerName string // RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule @@ -514,11 +512,7 @@ func (f *ConfigFactory) getNextPod() *v1.Pod { } func (f *ConfigFactory) ResponsibleForPod(pod *v1.Pod) bool { - if f.schedulerName == v1.DefaultSchedulerName { - return pod.Annotations[SchedulerAnnotationKey] == f.schedulerName || pod.Annotations[SchedulerAnnotationKey] == "" - } else { - return pod.Annotations[SchedulerAnnotationKey] == f.schedulerName - } + return f.schedulerName == pod.Spec.SchedulerName } func getNodeConditionPredicate() cache.NodeConditionPredicate { diff --git a/plugin/pkg/scheduler/factory/factory_test.go b/plugin/pkg/scheduler/factory/factory_test.go index 6c7c6bb5b2d..e8e1b8f3834 100644 --- a/plugin/pkg/scheduler/factory/factory_test.go +++ b/plugin/pkg/scheduler/factory/factory_test.go @@ -251,39 +251,33 @@ func TestResponsibleForPod(t *testing.T) { // factory of "foo-scheduler" factoryFooScheduler := NewConfigFactory(client, "foo-scheduler", v1.DefaultHardPodAffinitySymmetricWeight, v1.DefaultFailureDomains) // scheduler annotations to be tested - schedulerAnnotationFitsDefault := map[string]string{"scheduler.alpha.kubernetes.io/name": "default-scheduler"} - schedulerAnnotationFitsFoo := map[string]string{"scheduler.alpha.kubernetes.io/name": "foo-scheduler"} - schedulerAnnotationFitsNone := map[string]string{"scheduler.alpha.kubernetes.io/name": "bar-scheduler"} + schedulerFitsDefault := "default-scheduler" + schedulerFitsFoo := "foo-scheduler" + schedulerFitsNone := "bar-scheduler" + tests := []struct { pod *v1.Pod pickedByDefault bool pickedByFoo bool }{ { - // pod with no annotation "scheduler.alpha.kubernetes.io/name=" should be - // picked by the default scheduler, NOT by the one of name "foo-scheduler" - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}}, - pickedByDefault: true, - pickedByFoo: false, - }, - { - // pod with annotation "scheduler.alpha.kubernetes.io/name=default-scheduler" should be picked + // pod with "spec.Schedulername=default-scheduler" should be picked // by the scheduler of name "default-scheduler", NOT by the one of name "foo-scheduler" - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar", Annotations: schedulerAnnotationFitsDefault}}, + pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: v1.PodSpec{SchedulerName: schedulerFitsDefault}}, pickedByDefault: true, pickedByFoo: false, }, { - // pod with annotataion "scheduler.alpha.kubernetes.io/name=foo-scheduler" should be NOT + // pod with "spec.SchedulerName=foo-scheduler" should be NOT // be picked by the scheduler of name "default-scheduler", but by the one of name "foo-scheduler" - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar", Annotations: schedulerAnnotationFitsFoo}}, + pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: v1.PodSpec{SchedulerName: schedulerFitsFoo}}, pickedByDefault: false, pickedByFoo: true, }, { - // pod with annotataion "scheduler.alpha.kubernetes.io/name=foo-scheduler" should be NOT + // pod with "spec.SchedulerName=foo-scheduler" should be NOT // be picked by niether the scheduler of name "default-scheduler" nor the one of name "foo-scheduler" - pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar", Annotations: schedulerAnnotationFitsNone}}, + pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: v1.PodSpec{SchedulerName: schedulerFitsNone}}, pickedByDefault: false, pickedByFoo: false, }, diff --git a/staging/src/k8s.io/client-go/pkg/apis/componentconfig/types.go b/staging/src/k8s.io/client-go/pkg/apis/componentconfig/types.go index 4bba16bab1c..0a39e0828a7 100644 --- a/staging/src/k8s.io/client-go/pkg/apis/componentconfig/types.go +++ b/staging/src/k8s.io/client-go/pkg/apis/componentconfig/types.go @@ -561,8 +561,7 @@ type KubeSchedulerConfiguration struct { // kubeAPIBurst is the QPS burst to use while talking with kubernetes apiserver. KubeAPIBurst int32 // schedulerName is name of the scheduler, used to select which pods - // will be processed by this scheduler, based on pod's annotation with - // key 'scheduler.alpha.kubernetes.io/name'. + // will be processed by this scheduler, based on pod's "spec.SchedulerName". SchedulerName string // RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule // corresponding to every RequiredDuringScheduling affinity rule. diff --git a/staging/src/k8s.io/client-go/pkg/apis/componentconfig/v1alpha1/types.go b/staging/src/k8s.io/client-go/pkg/apis/componentconfig/v1alpha1/types.go index 2b5281d9d16..fac5c0c0048 100644 --- a/staging/src/k8s.io/client-go/pkg/apis/componentconfig/v1alpha1/types.go +++ b/staging/src/k8s.io/client-go/pkg/apis/componentconfig/v1alpha1/types.go @@ -122,8 +122,7 @@ type KubeSchedulerConfiguration struct { // kubeAPIBurst is the QPS burst to use while talking with kubernetes apiserver. KubeAPIBurst int `json:"kubeAPIBurst"` // schedulerName is name of the scheduler, used to select which pods - // will be processed by this scheduler, based on pod's annotation with - // key 'scheduler.alpha.kubernetes.io/name'. + // will be processed by this scheduler, based on pod's "spec.SchedulerName". SchedulerName string `json:"schedulerName"` // RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule // corresponding to every RequiredDuringScheduling affinity rule. diff --git a/test/e2e/pod_gc.go b/test/e2e/pod_gc.go index 91d21cfbb25..c6b1c84f691 100644 --- a/test/e2e/pod_gc.go +++ b/test/e2e/pod_gc.go @@ -84,9 +84,6 @@ func createTerminatingPod(f *framework.Framework) (*v1.Pod, error) { pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: string(uuid), - Annotations: map[string]string{ - "scheduler.alpha.kubernetes.io/name": "please don't schedule my pods", - }, }, Spec: v1.PodSpec{ Containers: []v1.Container{ @@ -95,6 +92,7 @@ func createTerminatingPod(f *framework.Framework) (*v1.Pod, error) { Image: "gcr.io/google_containers/busybox:1.24", }, }, + SchedulerName: "please don't schedule my pods", }, } return f.ClientSet.Core().Pods(f.Namespace.Name).Create(pod) diff --git a/test/integration/scheduler/scheduler_test.go b/test/integration/scheduler/scheduler_test.go index e69f49ae2d4..f7947e92562 100644 --- a/test/integration/scheduler/scheduler_test.go +++ b/test/integration/scheduler/scheduler_test.go @@ -352,48 +352,48 @@ func TestMultiScheduler(t *testing.T) { clientSet.Core().Nodes().Create(node) // 3. create 3 pods for testing - podWithNoAnnotation := createPod(clientSet, "pod-with-no-annotation", nil) - testPodNoAnnotation, err := clientSet.Core().Pods(ns.Name).Create(podWithNoAnnotation) + podWithoutSchedulerName := createPod(clientSet, "pod-without-scheduler-name", "") + testPod, err := clientSet.Core().Pods(ns.Name).Create(podWithoutSchedulerName) if err != nil { t.Fatalf("Failed to create pod: %v", err) } - schedulerAnnotationFitsDefault := map[string]string{"scheduler.alpha.kubernetes.io/name": "default-scheduler"} - podWithAnnotationFitsDefault := createPod(clientSet, "pod-with-annotation-fits-default", schedulerAnnotationFitsDefault) - testPodWithAnnotationFitsDefault, err := clientSet.Core().Pods(ns.Name).Create(podWithAnnotationFitsDefault) + schedulerFitsDefault := "default-scheduler" + podFitsDefault := createPod(clientSet, "pod-fits-default", schedulerFitsDefault) + testPodFitsDefault, err := clientSet.Core().Pods(ns.Name).Create(podFitsDefault) if err != nil { t.Fatalf("Failed to create pod: %v", err) } - schedulerAnnotationFitsFoo := map[string]string{"scheduler.alpha.kubernetes.io/name": "foo-scheduler"} - podWithAnnotationFitsFoo := createPod(clientSet, "pod-with-annotation-fits-foo", schedulerAnnotationFitsFoo) - testPodWithAnnotationFitsFoo, err := clientSet.Core().Pods(ns.Name).Create(podWithAnnotationFitsFoo) + schedulerFitsFoo := "foo-scheduler" + podFitsFoo := createPod(clientSet, "pod-fits-foo", schedulerFitsFoo) + testPodFitsFoo, err := clientSet.Core().Pods(ns.Name).Create(podFitsFoo) if err != nil { t.Fatalf("Failed to create pod: %v", err) } // 4. **check point-1**: - // - testPodNoAnnotation, testPodWithAnnotationFitsDefault should be scheduled - // - testPodWithAnnotationFitsFoo should NOT be scheduled - err = wait.Poll(time.Second, time.Second*5, podScheduled(clientSet, testPodNoAnnotation.Namespace, testPodNoAnnotation.Name)) + // - testPod, testPodFitsDefault should be scheduled + // - testPodFitsFoo should NOT be scheduled + err = wait.Poll(time.Second, time.Second*5, podScheduled(clientSet, testPod.Namespace, testPod.Name)) if err != nil { - t.Errorf("Test MultiScheduler: %s Pod not scheduled: %v", testPodNoAnnotation.Name, err) + t.Errorf("Test MultiScheduler: %s Pod not scheduled: %v", testPod.Name, err) } else { - t.Logf("Test MultiScheduler: %s Pod scheduled", testPodNoAnnotation.Name) + t.Logf("Test MultiScheduler: %s Pod scheduled", testPod.Name) } - err = wait.Poll(time.Second, time.Second*5, podScheduled(clientSet, testPodWithAnnotationFitsDefault.Namespace, testPodWithAnnotationFitsDefault.Name)) + err = wait.Poll(time.Second, time.Second*5, podScheduled(clientSet, testPodFitsDefault.Namespace, testPodFitsDefault.Name)) if err != nil { - t.Errorf("Test MultiScheduler: %s Pod not scheduled: %v", testPodWithAnnotationFitsDefault.Name, err) + t.Errorf("Test MultiScheduler: %s Pod not scheduled: %v", testPodFitsDefault.Name, err) } else { - t.Logf("Test MultiScheduler: %s Pod scheduled", testPodWithAnnotationFitsDefault.Name) + t.Logf("Test MultiScheduler: %s Pod scheduled", testPodFitsDefault.Name) } - err = wait.Poll(time.Second, time.Second*5, podScheduled(clientSet, testPodWithAnnotationFitsFoo.Namespace, testPodWithAnnotationFitsFoo.Name)) + err = wait.Poll(time.Second, time.Second*5, podScheduled(clientSet, testPodFitsFoo.Namespace, testPodFitsFoo.Name)) if err == nil { - t.Errorf("Test MultiScheduler: %s Pod got scheduled, %v", testPodWithAnnotationFitsFoo.Name, err) + t.Errorf("Test MultiScheduler: %s Pod got scheduled, %v", testPodFitsFoo.Name, err) } else { - t.Logf("Test MultiScheduler: %s Pod not scheduled", testPodWithAnnotationFitsFoo.Name) + t.Logf("Test MultiScheduler: %s Pod not scheduled", testPodFitsFoo.Name) } // 5. create and start a scheduler with name "foo-scheduler" @@ -413,19 +413,19 @@ func TestMultiScheduler(t *testing.T) { // 6. **check point-2**: // - testPodWithAnnotationFitsFoo should be scheduled - err = wait.Poll(time.Second, time.Second*5, podScheduled(clientSet, testPodWithAnnotationFitsFoo.Namespace, testPodWithAnnotationFitsFoo.Name)) + err = wait.Poll(time.Second, time.Second*5, podScheduled(clientSet, testPodFitsFoo.Namespace, testPodFitsFoo.Name)) if err != nil { - t.Errorf("Test MultiScheduler: %s Pod not scheduled, %v", testPodWithAnnotationFitsFoo.Name, err) + t.Errorf("Test MultiScheduler: %s Pod not scheduled, %v", testPodFitsFoo.Name, err) } else { - t.Logf("Test MultiScheduler: %s Pod scheduled", testPodWithAnnotationFitsFoo.Name) + t.Logf("Test MultiScheduler: %s Pod scheduled", testPodFitsFoo.Name) } // 7. delete the pods that were scheduled by the default scheduler, and stop the default scheduler - err = clientSet.Core().Pods(ns.Name).Delete(testPodNoAnnotation.Name, v1.NewDeleteOptions(0)) + err = clientSet.Core().Pods(ns.Name).Delete(testPod.Name, v1.NewDeleteOptions(0)) if err != nil { t.Errorf("Failed to delete pod: %v", err) } - err = clientSet.Core().Pods(ns.Name).Delete(testPodWithAnnotationFitsDefault.Name, v1.NewDeleteOptions(0)) + err = clientSet.Core().Pods(ns.Name).Delete(testPodFitsDefault.Name, v1.NewDeleteOptions(0)) if err != nil { t.Errorf("Failed to delete pod: %v", err) } @@ -469,11 +469,12 @@ func TestMultiScheduler(t *testing.T) { */ } -func createPod(client clientset.Interface, name string, annotation map[string]string) *v1.Pod { +func createPod(client clientset.Interface, name string, scheduler string) *v1.Pod { return &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: name, Annotations: annotation}, + ObjectMeta: metav1.ObjectMeta{Name: name}, Spec: v1.PodSpec{ - Containers: []v1.Container{{Name: "container", Image: e2e.GetPauseImageName(client)}}, + Containers: []v1.Container{{Name: "container", Image: e2e.GetPauseImageName(client)}}, + SchedulerName: scheduler, }, } }