From c649666b4addcb9cbef3ca5ca1d6d572e252f551 Mon Sep 17 00:00:00 2001 From: Wei Huang Date: Sat, 5 Oct 2019 16:23:46 -0700 Subject: [PATCH] manual API changes and code refactoring - add Policy API to pkg/scheduler/apis/config and staging/src/k8s.io/kube-scheduler/config/v1 - dual-register Policy as apiGroup "v1" and "kubescheduler.config.k8s.io - move/merge pkg/scheduler/api to pkg/scheduler/apis/config/... - alias schedulerapi to pkg/scheduler/apis/config - alias legacyapi to pkg/scheduler/api - eliminate latest.Codec; use scheme.Codecs instead - unit tests to verify Policy YAML with version "v1" or "kubescheduler.config.k8s.io/v1" can be loaded properly - update api/api-rules/violation_exceptions.list --- api/api-rules/violation_exceptions.list | 12 + .../algorithm/predicates/predicates.go | 4 +- .../algorithm/predicates/predicates_test.go | 16 +- pkg/scheduler/algorithm/types.go | 4 +- pkg/scheduler/algorithm_factory.go | 15 +- pkg/scheduler/algorithm_factory_test.go | 16 +- pkg/scheduler/api/latest/BUILD | 34 -- pkg/scheduler/api/latest/latest.go | 56 --- pkg/scheduler/api/v1/BUILD | 37 -- pkg/scheduler/api/v1/zz_generated.deepcopy.go | 375 ------------------ pkg/scheduler/api/validation/BUILD | 45 --- pkg/scheduler/api/validation/validation.go | 133 ------- .../api/validation/validation_test.go | 135 ------- pkg/scheduler/api/zz_generated.deepcopy.go | 375 ------------------ .../types.go => apis/config/legacy_types.go} | 26 +- pkg/scheduler/apis/config/register.go | 2 + pkg/scheduler/apis/config/scheme/scheme.go | 2 + .../config/testing}/BUILD | 2 +- .../config/testing}/compatibility_test.go | 94 +++-- .../apis/config/testing/policy_test.go | 108 +++++ pkg/scheduler/apis/config/types.go | 22 +- pkg/scheduler/{api => apis/config}/v1/doc.go | 8 +- .../{api => apis/config}/v1/register.go | 36 +- .../apis/config/validation/validation.go | 110 +++++ .../apis/config/validation/validation_test.go | 111 ++++++ pkg/scheduler/core/extender.go | 6 +- pkg/scheduler/core/extender_test.go | 2 +- pkg/scheduler/core/generic_scheduler.go | 4 +- pkg/scheduler/core/generic_scheduler_test.go | 23 +- pkg/scheduler/factory.go | 43 +- pkg/scheduler/factory_test.go | 87 ++-- pkg/scheduler/framework/v1alpha1/interface.go | 3 - pkg/scheduler/scheduler.go | 25 +- pkg/scheduler/scheduler_test.go | 2 +- .../k8s.io/kube-scheduler/config/v1}/doc.go | 5 +- .../kube-scheduler/config/v1}/register.go | 28 +- .../k8s.io/kube-scheduler/config}/v1/types.go | 23 +- test/integration/scheduler/extender_test.go | 4 +- test/integration/scheduler/util.go | 30 +- 39 files changed, 600 insertions(+), 1463 deletions(-) delete mode 100644 pkg/scheduler/api/latest/BUILD delete mode 100644 pkg/scheduler/api/latest/latest.go delete mode 100644 pkg/scheduler/api/v1/BUILD delete mode 100644 pkg/scheduler/api/v1/zz_generated.deepcopy.go delete mode 100644 pkg/scheduler/api/validation/BUILD delete mode 100644 pkg/scheduler/api/validation/validation.go delete mode 100644 pkg/scheduler/api/validation/validation_test.go delete mode 100644 pkg/scheduler/api/zz_generated.deepcopy.go rename pkg/scheduler/{api/types.go => apis/config/legacy_types.go} (94%) rename pkg/scheduler/{api/compatibility => apis/config/testing}/BUILD (95%) rename pkg/scheduler/{api/compatibility => apis/config/testing}/compatibility_test.go (93%) create mode 100644 pkg/scheduler/apis/config/testing/policy_test.go rename pkg/scheduler/{api => apis/config}/v1/doc.go (62%) rename pkg/scheduler/{api => apis/config}/v1/register.go (55%) rename {pkg/scheduler/api => staging/src/k8s.io/kube-scheduler/config/v1}/doc.go (83%) rename {pkg/scheduler/api => staging/src/k8s.io/kube-scheduler/config/v1}/register.go (56%) rename {pkg/scheduler/api => staging/src/k8s.io/kube-scheduler/config}/v1/types.go (94%) diff --git a/api/api-rules/violation_exceptions.list b/api/api-rules/violation_exceptions.list index 9cdb7889e10..2e39b58f31c 100644 --- a/api/api-rules/violation_exceptions.list +++ b/api/api-rules/violation_exceptions.list @@ -475,6 +475,17 @@ API rule violation: list_type_missing,k8s.io/kube-controller-manager/config/v1al API rule violation: list_type_missing,k8s.io/kube-controller-manager/config/v1alpha1,GenericControllerManagerConfiguration,Controllers API rule violation: list_type_missing,k8s.io/kube-proxy/config/v1alpha1,KubeProxyConfiguration,NodePortAddresses API rule violation: list_type_missing,k8s.io/kube-proxy/config/v1alpha1,KubeProxyIPVSConfiguration,ExcludeCIDRs +API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,Extender,ManagedResources +API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,ExtenderTLSConfig,CAData +API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,ExtenderTLSConfig,CertData +API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,ExtenderTLSConfig,KeyData +API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,LabelsPresence,Labels +API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,Policy,Extenders +API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,Policy,Predicates +API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,Policy,Priorities +API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,RequestedToCapacityRatioArguments,Resources +API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,RequestedToCapacityRatioArguments,Shape +API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,ServiceAffinity,Labels API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1alpha1,KubeSchedulerConfiguration,PluginConfig API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1alpha1,PluginSet,Disabled API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1alpha1,PluginSet,Enabled @@ -683,6 +694,7 @@ API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,V API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,VolumeConfiguration,FlexVolumePluginDir API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,VolumeConfiguration,PersistentVolumeRecyclerConfiguration API rule violation: names_match,k8s.io/kube-proxy/config/v1alpha1,KubeProxyConfiguration,IPTables +API rule violation: names_match,k8s.io/kube-scheduler/config/v1,Extender,EnableHTTPS API rule violation: names_match,k8s.io/kubelet/config/v1beta1,KubeletConfiguration,IPTablesDropBit API rule violation: names_match,k8s.io/kubelet/config/v1beta1,KubeletConfiguration,IPTablesMasqueradeBit API rule violation: names_match,k8s.io/kubelet/config/v1beta1,KubeletConfiguration,ResolverConfig diff --git a/pkg/scheduler/algorithm/predicates/predicates.go b/pkg/scheduler/algorithm/predicates/predicates.go index 0104bcd43b3..6a0bd20766b 100644 --- a/pkg/scheduler/algorithm/predicates/predicates.go +++ b/pkg/scheduler/algorithm/predicates/predicates.go @@ -43,7 +43,7 @@ import ( "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/scheduler/algorithm" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + legacyapi "k8s.io/kubernetes/pkg/scheduler/api" schedulerlisters "k8s.io/kubernetes/pkg/scheduler/listers" schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" schedutil "k8s.io/kubernetes/pkg/scheduler/util" @@ -1520,7 +1520,7 @@ func CheckNodeUnschedulablePredicate(pod *v1.Pod, meta PredicateMetadata, nodeIn // If pod tolerate unschedulable taint, it's also tolerate `node.Spec.Unschedulable`. podToleratesUnschedulable := v1helper.TolerationsTolerateTaint(pod.Spec.Tolerations, &v1.Taint{ - Key: schedulerapi.TaintNodeUnschedulable, + Key: legacyapi.TaintNodeUnschedulable, Effect: v1.TaintEffectNoSchedule, }) diff --git a/pkg/scheduler/algorithm/predicates/predicates_test.go b/pkg/scheduler/algorithm/predicates/predicates_test.go index 935cf45c7ae..ec61bcb2160 100644 --- a/pkg/scheduler/algorithm/predicates/predicates_test.go +++ b/pkg/scheduler/algorithm/predicates/predicates_test.go @@ -33,7 +33,7 @@ import ( featuregatetesting "k8s.io/component-base/featuregate/testing" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/features" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + legacyapi "k8s.io/kubernetes/pkg/scheduler/api" fakelisters "k8s.io/kubernetes/pkg/scheduler/listers/fake" schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" nodeinfosnapshot "k8s.io/kubernetes/pkg/scheduler/nodeinfo/snapshot" @@ -1447,7 +1447,7 @@ func TestPodFitsSelector(t *testing.T) { { MatchFields: []v1.NodeSelectorRequirement{ { - Key: schedulerapi.NodeFieldSelectorKeyNodeName, + Key: legacyapi.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, Values: []string{"node_1"}, }, @@ -1473,7 +1473,7 @@ func TestPodFitsSelector(t *testing.T) { { MatchFields: []v1.NodeSelectorRequirement{ { - Key: schedulerapi.NodeFieldSelectorKeyNodeName, + Key: legacyapi.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, Values: []string{"node_1"}, }, @@ -1499,7 +1499,7 @@ func TestPodFitsSelector(t *testing.T) { { MatchFields: []v1.NodeSelectorRequirement{ { - Key: schedulerapi.NodeFieldSelectorKeyNodeName, + Key: legacyapi.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, Values: []string{"node_1"}, }, @@ -1535,7 +1535,7 @@ func TestPodFitsSelector(t *testing.T) { { MatchFields: []v1.NodeSelectorRequirement{ { - Key: schedulerapi.NodeFieldSelectorKeyNodeName, + Key: legacyapi.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, Values: []string{"node_1"}, }, @@ -1569,7 +1569,7 @@ func TestPodFitsSelector(t *testing.T) { { MatchFields: []v1.NodeSelectorRequirement{ { - Key: schedulerapi.NodeFieldSelectorKeyNodeName, + Key: legacyapi.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, Values: []string{"node_1"}, }, @@ -1603,7 +1603,7 @@ func TestPodFitsSelector(t *testing.T) { { MatchFields: []v1.NodeSelectorRequirement{ { - Key: schedulerapi.NodeFieldSelectorKeyNodeName, + Key: legacyapi.NodeFieldSelectorKeyNodeName, Operator: v1.NodeSelectorOpIn, Values: []string{"node_1"}, }, @@ -4690,7 +4690,7 @@ func TestCheckNodeUnschedulablePredicate(t *testing.T) { Spec: v1.PodSpec{ Tolerations: []v1.Toleration{ { - Key: schedulerapi.TaintNodeUnschedulable, + Key: legacyapi.TaintNodeUnschedulable, Effect: v1.TaintEffectNoSchedule, }, }, diff --git a/pkg/scheduler/algorithm/types.go b/pkg/scheduler/algorithm/types.go index d1a02b9581c..0dbdbf6f40f 100644 --- a/pkg/scheduler/algorithm/types.go +++ b/pkg/scheduler/algorithm/types.go @@ -23,13 +23,13 @@ import ( appslisters "k8s.io/client-go/listers/apps/v1" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/kubernetes/pkg/apis/apps" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + legacyapi "k8s.io/kubernetes/pkg/scheduler/api" ) // NodeFieldSelectorKeys is a map that: the keys are node field selector keys; the values are // the functions to get the value of the node field. var NodeFieldSelectorKeys = map[string]func(*v1.Node) string{ - schedulerapi.NodeFieldSelectorKeyNodeName: func(n *v1.Node) string { return n.Name }, + legacyapi.NodeFieldSelectorKeyNodeName: func(n *v1.Node) string { return n.Name }, } var _ corelisters.ReplicationControllerLister = &EmptyControllerLister{} diff --git a/pkg/scheduler/algorithm_factory.go b/pkg/scheduler/algorithm_factory.go index 85890523bb0..e431f0e4bac 100644 --- a/pkg/scheduler/algorithm_factory.go +++ b/pkg/scheduler/algorithm_factory.go @@ -23,6 +23,7 @@ import ( "strings" "sync" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/sets" appslisters "k8s.io/client-go/listers/apps/v1" corelisters "k8s.io/client-go/listers/core/v1" @@ -31,7 +32,7 @@ import ( v1beta1storagelisters "k8s.io/client-go/listers/storage/v1beta1" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/framework/plugins" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodelabel" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/requestedtocapacityratio" @@ -436,15 +437,15 @@ func RegisterCustomPriorityFunction(policy schedulerapi.PriorityPolicy, args *pl } func buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(arguments *schedulerapi.RequestedToCapacityRatioArguments) (priorities.FunctionShape, priorities.ResourceToWeightMap) { - n := len(arguments.UtilizationShape) + n := len(arguments.Shape) points := make([]priorities.FunctionShapePoint, 0, n) - for _, point := range arguments.UtilizationShape { + for _, point := range arguments.Shape { points = append(points, priorities.FunctionShapePoint{ Utilization: int64(point.Utilization), - // CustomPriorityMaxScore may diverge from the max score used in the scheduler and defined by MaxNodeScore, + // MaxCustomPriorityScore may diverge from the max score used in the scheduler and defined by MaxNodeScore, // therefore we need to scale the score returned by requested to capacity ratio to the score range // used by the scheduler. - Score: int64(point.Score) * (framework.MaxNodeScore / schedulerapi.CustomPriorityMaxScore), + Score: int64(point.Score) * (framework.MaxNodeScore / schedulerapi.MaxCustomPriorityScore), }) } shape, err := priorities.NewFunctionShape(points) @@ -457,9 +458,9 @@ func buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(arguments *s return shape, resourceToWeightMap } for _, resource := range arguments.Resources { - resourceToWeightMap[resource.Name] = int64(resource.Weight) + resourceToWeightMap[v1.ResourceName(resource.Name)] = resource.Weight if resource.Weight == 0 { - resourceToWeightMap[resource.Name] = 1 + resourceToWeightMap[v1.ResourceName(resource.Name)] = 1 } } return shape, resourceToWeightMap diff --git a/pkg/scheduler/algorithm_factory_test.go b/pkg/scheduler/algorithm_factory_test.go index 1cdd837f7b0..3f358276952 100644 --- a/pkg/scheduler/algorithm_factory_test.go +++ b/pkg/scheduler/algorithm_factory_test.go @@ -22,7 +22,7 @@ import ( "github.com/stretchr/testify/assert" v1 "k8s.io/api/core/v1" "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" - "k8s.io/kubernetes/pkg/scheduler/api" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" ) func TestAlgorithmNameValidation(t *testing.T) { @@ -52,15 +52,15 @@ func TestAlgorithmNameValidation(t *testing.T) { } func TestBuildScoringFunctionShapeFromRequestedToCapacityRatioArguments(t *testing.T) { - arguments := api.RequestedToCapacityRatioArguments{ - UtilizationShape: []api.UtilizationShapePoint{ + arguments := schedulerapi.RequestedToCapacityRatioArguments{ + Shape: []schedulerapi.UtilizationShapePoint{ {Utilization: 10, Score: 1}, {Utilization: 30, Score: 5}, {Utilization: 70, Score: 2}, }, - Resources: []api.ResourceSpec{ - {Name: v1.ResourceCPU}, - {Name: v1.ResourceMemory}, + Resources: []schedulerapi.ResourceSpec{ + {Name: string(v1.ResourceCPU)}, + {Name: string(v1.ResourceMemory)}, }, } builtShape, resources := buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(&arguments) @@ -78,8 +78,8 @@ func TestBuildScoringFunctionShapeFromRequestedToCapacityRatioArguments(t *testi } func TestBuildScoringFunctionShapeFromRequestedToCapacityRatioArgumentsNilResourceToWeightMap(t *testing.T) { - arguments := api.RequestedToCapacityRatioArguments{ - UtilizationShape: []api.UtilizationShapePoint{ + arguments := schedulerapi.RequestedToCapacityRatioArguments{ + Shape: []schedulerapi.UtilizationShapePoint{ {Utilization: 10, Score: 1}, {Utilization: 30, Score: 5}, {Utilization: 70, Score: 2}, diff --git a/pkg/scheduler/api/latest/BUILD b/pkg/scheduler/api/latest/BUILD deleted file mode 100644 index 65b4db771a0..00000000000 --- a/pkg/scheduler/api/latest/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["latest.go"], - importpath = "k8s.io/kubernetes/pkg/scheduler/api/latest", - deps = [ - "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/api/v1:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/yaml:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/scheduler/api/latest/latest.go b/pkg/scheduler/api/latest/latest.go deleted file mode 100644 index f4a4ff7adcf..00000000000 --- a/pkg/scheduler/api/latest/latest.go +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright 2014 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 latest - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/runtime/serializer/json" - "k8s.io/apimachinery/pkg/runtime/serializer/versioning" - "k8s.io/apimachinery/pkg/runtime/serializer/yaml" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - // Init the api v1 package - _ "k8s.io/kubernetes/pkg/scheduler/api/v1" -) - -// Version is the string that represents the current external default version. -const Version = "v1" - -// OldestVersion is the string that represents the oldest server version supported. -const OldestVersion = "v1" - -// Versions is the list of versions that are recognized in code. The order provided -// may be assumed to be least feature rich to most feature rich, and clients may -// choose to prefer the latter items in the list over the former items when presented -// with a set of versions to choose. -var Versions = []string{"v1"} - -// Codec is the default codec for serializing input that should use -// the latest supported version. It supports JSON by default. -var Codec runtime.Codec - -func init() { - jsonSerializer := json.NewSerializer(json.DefaultMetaFactory, schedulerapi.Scheme, schedulerapi.Scheme, true) - serializer := yaml.NewDecodingSerializer(jsonSerializer) - Codec = versioning.NewDefaultingCodecForScheme( - schedulerapi.Scheme, - serializer, - serializer, - schema.GroupVersion{Version: Version}, - runtime.InternalGroupVersioner, - ) -} diff --git a/pkg/scheduler/api/v1/BUILD b/pkg/scheduler/api/v1/BUILD deleted file mode 100644 index 905585f2439..00000000000 --- a/pkg/scheduler/api/v1/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "register.go", - "types.go", - "zz_generated.deepcopy.go", - ], - importpath = "k8s.io/kubernetes/pkg/scheduler/api/v1", - deps = [ - "//pkg/scheduler/api:go_default_library", - "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/scheduler/api/v1/zz_generated.deepcopy.go b/pkg/scheduler/api/v1/zz_generated.deepcopy.go deleted file mode 100644 index 149403d3108..00000000000 --- a/pkg/scheduler/api/v1/zz_generated.deepcopy.go +++ /dev/null @@ -1,375 +0,0 @@ -// +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 v1 - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExtenderConfig) DeepCopyInto(out *ExtenderConfig) { - *out = *in - if in.TLSConfig != nil { - in, out := &in.TLSConfig, &out.TLSConfig - *out = new(ExtenderTLSConfig) - (*in).DeepCopyInto(*out) - } - if in.ManagedResources != nil { - in, out := &in.ManagedResources, &out.ManagedResources - *out = make([]ExtenderManagedResource, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtenderConfig. -func (in *ExtenderConfig) DeepCopy() *ExtenderConfig { - if in == nil { - return nil - } - out := new(ExtenderConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExtenderManagedResource) DeepCopyInto(out *ExtenderManagedResource) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtenderManagedResource. -func (in *ExtenderManagedResource) DeepCopy() *ExtenderManagedResource { - if in == nil { - return nil - } - out := new(ExtenderManagedResource) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExtenderTLSConfig) DeepCopyInto(out *ExtenderTLSConfig) { - *out = *in - if in.CertData != nil { - in, out := &in.CertData, &out.CertData - *out = make([]byte, len(*in)) - copy(*out, *in) - } - if in.KeyData != nil { - in, out := &in.KeyData, &out.KeyData - *out = make([]byte, len(*in)) - copy(*out, *in) - } - if in.CAData != nil { - in, out := &in.CAData, &out.CAData - *out = make([]byte, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtenderTLSConfig. -func (in *ExtenderTLSConfig) DeepCopy() *ExtenderTLSConfig { - if in == nil { - return nil - } - out := new(ExtenderTLSConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *LabelPreference) DeepCopyInto(out *LabelPreference) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LabelPreference. -func (in *LabelPreference) DeepCopy() *LabelPreference { - if in == nil { - return nil - } - out := new(LabelPreference) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *LabelsPresence) DeepCopyInto(out *LabelsPresence) { - *out = *in - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LabelsPresence. -func (in *LabelsPresence) DeepCopy() *LabelsPresence { - if in == nil { - return nil - } - out := new(LabelsPresence) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Policy) DeepCopyInto(out *Policy) { - *out = *in - out.TypeMeta = in.TypeMeta - if in.Predicates != nil { - in, out := &in.Predicates, &out.Predicates - *out = make([]PredicatePolicy, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Priorities != nil { - in, out := &in.Priorities, &out.Priorities - *out = make([]PriorityPolicy, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.ExtenderConfigs != nil { - in, out := &in.ExtenderConfigs, &out.ExtenderConfigs - *out = make([]ExtenderConfig, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Policy. -func (in *Policy) DeepCopy() *Policy { - if in == nil { - return nil - } - out := new(Policy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Policy) 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 *PredicateArgument) DeepCopyInto(out *PredicateArgument) { - *out = *in - if in.ServiceAffinity != nil { - in, out := &in.ServiceAffinity, &out.ServiceAffinity - *out = new(ServiceAffinity) - (*in).DeepCopyInto(*out) - } - if in.LabelsPresence != nil { - in, out := &in.LabelsPresence, &out.LabelsPresence - *out = new(LabelsPresence) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PredicateArgument. -func (in *PredicateArgument) DeepCopy() *PredicateArgument { - if in == nil { - return nil - } - out := new(PredicateArgument) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PredicatePolicy) DeepCopyInto(out *PredicatePolicy) { - *out = *in - if in.Argument != nil { - in, out := &in.Argument, &out.Argument - *out = new(PredicateArgument) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PredicatePolicy. -func (in *PredicatePolicy) DeepCopy() *PredicatePolicy { - if in == nil { - return nil - } - out := new(PredicatePolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PriorityArgument) DeepCopyInto(out *PriorityArgument) { - *out = *in - if in.ServiceAntiAffinity != nil { - in, out := &in.ServiceAntiAffinity, &out.ServiceAntiAffinity - *out = new(ServiceAntiAffinity) - **out = **in - } - if in.LabelPreference != nil { - in, out := &in.LabelPreference, &out.LabelPreference - *out = new(LabelPreference) - **out = **in - } - if in.RequestedToCapacityRatioArguments != nil { - in, out := &in.RequestedToCapacityRatioArguments, &out.RequestedToCapacityRatioArguments - *out = new(RequestedToCapacityRatioArguments) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PriorityArgument. -func (in *PriorityArgument) DeepCopy() *PriorityArgument { - if in == nil { - return nil - } - out := new(PriorityArgument) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PriorityPolicy) DeepCopyInto(out *PriorityPolicy) { - *out = *in - if in.Argument != nil { - in, out := &in.Argument, &out.Argument - *out = new(PriorityArgument) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PriorityPolicy. -func (in *PriorityPolicy) DeepCopy() *PriorityPolicy { - if in == nil { - return nil - } - out := new(PriorityPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RequestedToCapacityRatioArguments) DeepCopyInto(out *RequestedToCapacityRatioArguments) { - *out = *in - if in.UtilizationShape != nil { - in, out := &in.UtilizationShape, &out.UtilizationShape - *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 RequestedToCapacityRatioArguments. -func (in *RequestedToCapacityRatioArguments) DeepCopy() *RequestedToCapacityRatioArguments { - if in == nil { - return nil - } - out := new(RequestedToCapacityRatioArguments) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ResourceSpec) DeepCopyInto(out *ResourceSpec) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceSpec. -func (in *ResourceSpec) DeepCopy() *ResourceSpec { - if in == nil { - return nil - } - out := new(ResourceSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceAffinity) DeepCopyInto(out *ServiceAffinity) { - *out = *in - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAffinity. -func (in *ServiceAffinity) DeepCopy() *ServiceAffinity { - if in == nil { - return nil - } - out := new(ServiceAffinity) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceAntiAffinity) DeepCopyInto(out *ServiceAntiAffinity) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAntiAffinity. -func (in *ServiceAntiAffinity) DeepCopy() *ServiceAntiAffinity { - if in == nil { - return nil - } - out := new(ServiceAntiAffinity) - 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 -} diff --git a/pkg/scheduler/api/validation/BUILD b/pkg/scheduler/api/validation/BUILD deleted file mode 100644 index 732e9daa546..00000000000 --- a/pkg/scheduler/api/validation/BUILD +++ /dev/null @@ -1,45 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = ["validation.go"], - importpath = "k8s.io/kubernetes/pkg/scheduler/api/validation", - deps = [ - "//pkg/apis/core/v1/helper:go_default_library", - "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/framework/v1alpha1:go_default_library", - "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["validation_test.go"], - embed = [":go_default_library"], - deps = [ - "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/framework/v1alpha1:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/scheduler/api/validation/validation.go b/pkg/scheduler/api/validation/validation.go deleted file mode 100644 index 82d8ba43115..00000000000 --- a/pkg/scheduler/api/validation/validation.go +++ /dev/null @@ -1,133 +0,0 @@ -/* -Copyright 2015 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 validation - -import ( - "errors" - "fmt" - - v1 "k8s.io/api/core/v1" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/apimachinery/pkg/util/validation" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" -) - -// ValidatePolicy checks for errors in the Config -// It does not return early so that it can find as many errors as possible -func ValidatePolicy(policy schedulerapi.Policy) error { - var validationErrors []error - - priorities := make(map[string]schedulerapi.PriorityPolicy, len(policy.Priorities)) - for _, priority := range policy.Priorities { - if priority.Weight <= 0 || priority.Weight >= framework.MaxWeight { - validationErrors = append(validationErrors, fmt.Errorf("Priority %s should have a positive weight applied to it or it has overflown", priority.Name)) - } - - validationErrors = append(validationErrors, validatePriorityRedeclared(priorities, priority)) - } - - predicates := make(map[string]schedulerapi.PredicatePolicy, len(policy.Predicates)) - for _, predicate := range policy.Predicates { - validationErrors = append(validationErrors, validatePredicateRedeclared(predicates, predicate)) - } - - binders := 0 - extenderManagedResources := sets.NewString() - for _, extender := range policy.ExtenderConfigs { - if len(extender.PrioritizeVerb) > 0 && extender.Weight <= 0 { - validationErrors = append(validationErrors, fmt.Errorf("Priority for extender %s should have a positive weight applied to it", extender.URLPrefix)) - } - if extender.BindVerb != "" { - binders++ - } - for _, resource := range extender.ManagedResources { - errs := validateExtendedResourceName(resource.Name) - if len(errs) != 0 { - validationErrors = append(validationErrors, errs...) - } - if extenderManagedResources.Has(string(resource.Name)) { - validationErrors = append(validationErrors, fmt.Errorf("Duplicate extender managed resource name %s", string(resource.Name))) - } - extenderManagedResources.Insert(string(resource.Name)) - } - } - if binders > 1 { - validationErrors = append(validationErrors, fmt.Errorf("Only one extender can implement bind, found %v", binders)) - } - return utilerrors.NewAggregate(validationErrors) -} - -// validatePriorityRedeclared checks if any custom priorities have been declared multiple times in the policy config -// by examining the specified priority arguments -func validatePriorityRedeclared(priorities map[string]schedulerapi.PriorityPolicy, priority schedulerapi.PriorityPolicy) error { - var priorityType string - if priority.Argument != nil { - if priority.Argument.LabelPreference != nil { - priorityType = "LabelPreference" - } else if priority.Argument.RequestedToCapacityRatioArguments != nil { - priorityType = "RequestedToCapacityRatioArguments" - } else if priority.Argument.ServiceAntiAffinity != nil { - priorityType = "ServiceAntiAffinity" - } else { - return fmt.Errorf("No priority arguments set for priority %s", priority.Name) - } - if existing, alreadyDeclared := priorities[priorityType]; alreadyDeclared { - return fmt.Errorf("Priority '%s' redeclares custom priority '%s', from:'%s'", priority.Name, priorityType, existing.Name) - } - priorities[priorityType] = priority - } - return nil -} - -// validatePredicateRedeclared checks if any custom predicates have been declared multiple times in the policy config -// by examining the specified predicate arguments -func validatePredicateRedeclared(predicates map[string]schedulerapi.PredicatePolicy, predicate schedulerapi.PredicatePolicy) error { - var predicateType string - if predicate.Argument != nil { - if predicate.Argument.LabelsPresence != nil { - predicateType = "LabelsPresence" - } else if predicate.Argument.ServiceAffinity != nil { - predicateType = "ServiceAffinity" - } else { - return fmt.Errorf("No priority arguments set for priority %s", predicate.Name) - } - if existing, alreadyDeclared := predicates[predicateType]; alreadyDeclared { - return fmt.Errorf("Predicate '%s' redeclares custom predicate '%s', from:'%s'", predicate.Name, predicateType, existing.Name) - } - predicates[predicateType] = predicate - } - return nil -} - -// validateExtendedResourceName checks whether the specified name is a valid -// extended resource name. -func validateExtendedResourceName(name v1.ResourceName) []error { - var validationErrors []error - for _, msg := range validation.IsQualifiedName(string(name)) { - validationErrors = append(validationErrors, errors.New(msg)) - } - if len(validationErrors) != 0 { - return validationErrors - } - if !v1helper.IsExtendedResourceName(name) { - validationErrors = append(validationErrors, fmt.Errorf("%s is an invalid extended resource name", name)) - } - return validationErrors -} diff --git a/pkg/scheduler/api/validation/validation_test.go b/pkg/scheduler/api/validation/validation_test.go deleted file mode 100644 index 2f4dfc4ab8d..00000000000 --- a/pkg/scheduler/api/validation/validation_test.go +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright 2015 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 validation - -import ( - "errors" - "fmt" - "testing" - - "k8s.io/kubernetes/pkg/scheduler/api" - framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" -) - -func TestValidatePolicy(t *testing.T) { - tests := []struct { - policy api.Policy - expected error - name string - }{ - { - name: "no weight defined in policy", - policy: api.Policy{Priorities: []api.PriorityPolicy{{Name: "NoWeightPriority"}}}, - expected: errors.New("Priority NoWeightPriority should have a positive weight applied to it or it has overflown"), - }, - { - name: "policy weight is not positive", - policy: api.Policy{Priorities: []api.PriorityPolicy{{Name: "NoWeightPriority", Weight: 0}}}, - expected: errors.New("Priority NoWeightPriority should have a positive weight applied to it or it has overflown"), - }, - { - name: "valid weight priority", - policy: api.Policy{Priorities: []api.PriorityPolicy{{Name: "WeightPriority", Weight: 2}}}, - expected: nil, - }, - { - name: "invalid negative weight policy", - policy: api.Policy{Priorities: []api.PriorityPolicy{{Name: "WeightPriority", Weight: -2}}}, - expected: errors.New("Priority WeightPriority should have a positive weight applied to it or it has overflown"), - }, - { - name: "policy weight exceeds maximum", - policy: api.Policy{Priorities: []api.PriorityPolicy{{Name: "WeightPriority", Weight: framework.MaxWeight}}}, - expected: errors.New("Priority WeightPriority should have a positive weight applied to it or it has overflown"), - }, - { - name: "valid weight in policy extender config", - policy: api.Policy{ExtenderConfigs: []api.ExtenderConfig{{URLPrefix: "http://127.0.0.1:8081/extender", PrioritizeVerb: "prioritize", Weight: 2}}}, - expected: nil, - }, - { - name: "invalid negative weight in policy extender config", - policy: api.Policy{ExtenderConfigs: []api.ExtenderConfig{{URLPrefix: "http://127.0.0.1:8081/extender", PrioritizeVerb: "prioritize", Weight: -2}}}, - expected: errors.New("Priority for extender http://127.0.0.1:8081/extender should have a positive weight applied to it"), - }, - { - name: "valid filter verb and url prefix", - policy: api.Policy{ExtenderConfigs: []api.ExtenderConfig{{URLPrefix: "http://127.0.0.1:8081/extender", FilterVerb: "filter"}}}, - expected: nil, - }, - { - name: "valid preemt verb and urlprefix", - policy: api.Policy{ExtenderConfigs: []api.ExtenderConfig{{URLPrefix: "http://127.0.0.1:8081/extender", PreemptVerb: "preempt"}}}, - expected: nil, - }, - { - name: "invalid multiple extenders", - policy: api.Policy{ - ExtenderConfigs: []api.ExtenderConfig{ - {URLPrefix: "http://127.0.0.1:8081/extender", BindVerb: "bind"}, - {URLPrefix: "http://127.0.0.1:8082/extender", BindVerb: "bind"}, - }}, - expected: errors.New("Only one extender can implement bind, found 2"), - }, - { - name: "invalid duplicate extender resource name", - policy: api.Policy{ - ExtenderConfigs: []api.ExtenderConfig{ - {URLPrefix: "http://127.0.0.1:8081/extender", ManagedResources: []api.ExtenderManagedResource{{Name: "foo.com/bar"}}}, - {URLPrefix: "http://127.0.0.1:8082/extender", BindVerb: "bind", ManagedResources: []api.ExtenderManagedResource{{Name: "foo.com/bar"}}}, - }}, - expected: errors.New("Duplicate extender managed resource name foo.com/bar"), - }, - { - name: "invalid extended resource name", - policy: api.Policy{ - ExtenderConfigs: []api.ExtenderConfig{ - {URLPrefix: "http://127.0.0.1:8081/extender", ManagedResources: []api.ExtenderManagedResource{{Name: "kubernetes.io/foo"}}}, - }}, - expected: errors.New("kubernetes.io/foo is an invalid extended resource name"), - }, - { - name: "invalid redeclared custom predicate", - policy: api.Policy{ - Predicates: []api.PredicatePolicy{ - {Name: "customPredicate1", Argument: &api.PredicateArgument{ServiceAffinity: &api.ServiceAffinity{Labels: []string{"label1"}}}}, - {Name: "customPredicate2", Argument: &api.PredicateArgument{ServiceAffinity: &api.ServiceAffinity{Labels: []string{"label2"}}}}, - }, - }, - expected: errors.New("Predicate 'customPredicate2' redeclares custom predicate 'ServiceAffinity', from:'customPredicate1'"), - }, - { - name: "invalid redeclared custom priority", - policy: api.Policy{ - Priorities: []api.PriorityPolicy{ - {Name: "customPriority1", Weight: 1, Argument: &api.PriorityArgument{ServiceAntiAffinity: &api.ServiceAntiAffinity{Label: "label1"}}}, - {Name: "customPriority2", Weight: 1, Argument: &api.PriorityArgument{ServiceAntiAffinity: &api.ServiceAntiAffinity{Label: "label2"}}}, - }, - }, - expected: errors.New("Priority 'customPriority2' redeclares custom priority 'ServiceAntiAffinity', from:'customPriority1'"), - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - actual := ValidatePolicy(test.policy) - if fmt.Sprint(test.expected) != fmt.Sprint(actual) { - t.Errorf("expected: %s, actual: %s", test.expected, actual) - } - }) - } -} diff --git a/pkg/scheduler/api/zz_generated.deepcopy.go b/pkg/scheduler/api/zz_generated.deepcopy.go deleted file mode 100644 index 052923578eb..00000000000 --- a/pkg/scheduler/api/zz_generated.deepcopy.go +++ /dev/null @@ -1,375 +0,0 @@ -// +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 api - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExtenderConfig) DeepCopyInto(out *ExtenderConfig) { - *out = *in - if in.TLSConfig != nil { - in, out := &in.TLSConfig, &out.TLSConfig - *out = new(ExtenderTLSConfig) - (*in).DeepCopyInto(*out) - } - if in.ManagedResources != nil { - in, out := &in.ManagedResources, &out.ManagedResources - *out = make([]ExtenderManagedResource, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtenderConfig. -func (in *ExtenderConfig) DeepCopy() *ExtenderConfig { - if in == nil { - return nil - } - out := new(ExtenderConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExtenderManagedResource) DeepCopyInto(out *ExtenderManagedResource) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtenderManagedResource. -func (in *ExtenderManagedResource) DeepCopy() *ExtenderManagedResource { - if in == nil { - return nil - } - out := new(ExtenderManagedResource) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExtenderTLSConfig) DeepCopyInto(out *ExtenderTLSConfig) { - *out = *in - if in.CertData != nil { - in, out := &in.CertData, &out.CertData - *out = make([]byte, len(*in)) - copy(*out, *in) - } - if in.KeyData != nil { - in, out := &in.KeyData, &out.KeyData - *out = make([]byte, len(*in)) - copy(*out, *in) - } - if in.CAData != nil { - in, out := &in.CAData, &out.CAData - *out = make([]byte, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtenderTLSConfig. -func (in *ExtenderTLSConfig) DeepCopy() *ExtenderTLSConfig { - if in == nil { - return nil - } - out := new(ExtenderTLSConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *LabelPreference) DeepCopyInto(out *LabelPreference) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LabelPreference. -func (in *LabelPreference) DeepCopy() *LabelPreference { - if in == nil { - return nil - } - out := new(LabelPreference) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *LabelsPresence) DeepCopyInto(out *LabelsPresence) { - *out = *in - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LabelsPresence. -func (in *LabelsPresence) DeepCopy() *LabelsPresence { - if in == nil { - return nil - } - out := new(LabelsPresence) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Policy) DeepCopyInto(out *Policy) { - *out = *in - out.TypeMeta = in.TypeMeta - if in.Predicates != nil { - in, out := &in.Predicates, &out.Predicates - *out = make([]PredicatePolicy, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Priorities != nil { - in, out := &in.Priorities, &out.Priorities - *out = make([]PriorityPolicy, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.ExtenderConfigs != nil { - in, out := &in.ExtenderConfigs, &out.ExtenderConfigs - *out = make([]ExtenderConfig, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Policy. -func (in *Policy) DeepCopy() *Policy { - if in == nil { - return nil - } - out := new(Policy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Policy) 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 *PredicateArgument) DeepCopyInto(out *PredicateArgument) { - *out = *in - if in.ServiceAffinity != nil { - in, out := &in.ServiceAffinity, &out.ServiceAffinity - *out = new(ServiceAffinity) - (*in).DeepCopyInto(*out) - } - if in.LabelsPresence != nil { - in, out := &in.LabelsPresence, &out.LabelsPresence - *out = new(LabelsPresence) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PredicateArgument. -func (in *PredicateArgument) DeepCopy() *PredicateArgument { - if in == nil { - return nil - } - out := new(PredicateArgument) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PredicatePolicy) DeepCopyInto(out *PredicatePolicy) { - *out = *in - if in.Argument != nil { - in, out := &in.Argument, &out.Argument - *out = new(PredicateArgument) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PredicatePolicy. -func (in *PredicatePolicy) DeepCopy() *PredicatePolicy { - if in == nil { - return nil - } - out := new(PredicatePolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PriorityArgument) DeepCopyInto(out *PriorityArgument) { - *out = *in - if in.ServiceAntiAffinity != nil { - in, out := &in.ServiceAntiAffinity, &out.ServiceAntiAffinity - *out = new(ServiceAntiAffinity) - **out = **in - } - if in.LabelPreference != nil { - in, out := &in.LabelPreference, &out.LabelPreference - *out = new(LabelPreference) - **out = **in - } - if in.RequestedToCapacityRatioArguments != nil { - in, out := &in.RequestedToCapacityRatioArguments, &out.RequestedToCapacityRatioArguments - *out = new(RequestedToCapacityRatioArguments) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PriorityArgument. -func (in *PriorityArgument) DeepCopy() *PriorityArgument { - if in == nil { - return nil - } - out := new(PriorityArgument) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PriorityPolicy) DeepCopyInto(out *PriorityPolicy) { - *out = *in - if in.Argument != nil { - in, out := &in.Argument, &out.Argument - *out = new(PriorityArgument) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PriorityPolicy. -func (in *PriorityPolicy) DeepCopy() *PriorityPolicy { - if in == nil { - return nil - } - out := new(PriorityPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RequestedToCapacityRatioArguments) DeepCopyInto(out *RequestedToCapacityRatioArguments) { - *out = *in - if in.UtilizationShape != nil { - in, out := &in.UtilizationShape, &out.UtilizationShape - *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 RequestedToCapacityRatioArguments. -func (in *RequestedToCapacityRatioArguments) DeepCopy() *RequestedToCapacityRatioArguments { - if in == nil { - return nil - } - out := new(RequestedToCapacityRatioArguments) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ResourceSpec) DeepCopyInto(out *ResourceSpec) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceSpec. -func (in *ResourceSpec) DeepCopy() *ResourceSpec { - if in == nil { - return nil - } - out := new(ResourceSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceAffinity) DeepCopyInto(out *ServiceAffinity) { - *out = *in - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAffinity. -func (in *ServiceAffinity) DeepCopy() *ServiceAffinity { - if in == nil { - return nil - } - out := new(ServiceAffinity) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceAntiAffinity) DeepCopyInto(out *ServiceAntiAffinity) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAntiAffinity. -func (in *ServiceAntiAffinity) DeepCopy() *ServiceAntiAffinity { - if in == nil { - return nil - } - out := new(ServiceAntiAffinity) - 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 -} diff --git a/pkg/scheduler/api/types.go b/pkg/scheduler/apis/config/legacy_types.go similarity index 94% rename from pkg/scheduler/api/types.go rename to pkg/scheduler/apis/config/legacy_types.go index fff21dbdc89..4e5ffa1ee21 100644 --- a/pkg/scheduler/api/types.go +++ b/pkg/scheduler/apis/config/legacy_types.go @@ -14,24 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package api +package config import ( "time" - v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -const ( - // DefaultPercentageOfNodesToScore defines the percentage of nodes of all nodes - // that once found feasible, the scheduler stops looking for more nodes. - DefaultPercentageOfNodesToScore = 50 - - // CustomPriorityMaxScore is the max score UtilizationShapePoint expects. - CustomPriorityMaxScore int64 = 10 -) - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Policy describes a struct of a policy resource in api. @@ -47,7 +37,7 @@ type Policy struct { // If empty list, all priority functions will be bypassed. Priorities []PriorityPolicy // Holds the information to communicate with the extender(s) - ExtenderConfigs []ExtenderConfig + Extenders []Extender // RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule // corresponding to every RequiredDuringScheduling affinity rule. // HardPodAffinitySymmetricWeight represents the weight of implicit PreferredDuringScheduling affinity rule, in the range 1-100. @@ -142,8 +132,8 @@ type LabelPreference struct { // RequestedToCapacityRatioArguments holds arguments specific to RequestedToCapacityRatio priority function. type RequestedToCapacityRatioArguments struct { // Array of point defining priority function shape - UtilizationShape []UtilizationShapePoint - Resources []ResourceSpec + Shape []UtilizationShapePoint + Resources []ResourceSpec } // UtilizationShapePoint represents single point of priority function shape @@ -157,7 +147,7 @@ type UtilizationShapePoint struct { // ResourceSpec represents single resource for bin packing of priority RequestedToCapacityRatioArguments. type ResourceSpec struct { // Name of the resource to be managed by RequestedToCapacityRatio function. - Name v1.ResourceName + Name string // Weight of the resource. Weight int64 } @@ -166,7 +156,7 @@ type ResourceSpec struct { // managed by an extender. type ExtenderManagedResource struct { // Name is the extended resource name. - Name v1.ResourceName + Name string // IgnoredByScheduler indicates whether kube-scheduler should ignore this // resource when applying predicates. IgnoredByScheduler bool @@ -199,9 +189,9 @@ type ExtenderTLSConfig struct { CAData []byte } -// ExtenderConfig holds the parameters used to communicate with the extender. If a verb is unspecified/empty, +// 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 ExtenderConfig struct { +type Extender struct { // URLPrefix at which the extender is available URLPrefix string // Verb for the filter call, empty if not supported. This verb is appended to the URLPrefix when issuing the filter call to extender. diff --git a/pkg/scheduler/apis/config/register.go b/pkg/scheduler/apis/config/register.go index bb2c6bad89b..bb67672faef 100644 --- a/pkg/scheduler/apis/config/register.go +++ b/pkg/scheduler/apis/config/register.go @@ -38,6 +38,8 @@ var ( func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &KubeSchedulerConfiguration{}, + &Policy{}, ) + scheme.AddKnownTypes(schema.GroupVersion{Group: "", Version: runtime.APIVersionInternal}, &Policy{}) return nil } diff --git a/pkg/scheduler/apis/config/scheme/scheme.go b/pkg/scheduler/apis/config/scheme/scheme.go index 1a6ac1ca4d0..34f74a7f2c8 100644 --- a/pkg/scheduler/apis/config/scheme/scheme.go +++ b/pkg/scheduler/apis/config/scheme/scheme.go @@ -21,6 +21,7 @@ import ( "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" kubeschedulerconfigv1alpha1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1alpha1" ) @@ -39,6 +40,7 @@ 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(kubeschedulerconfigv1alpha1.AddToScheme(Scheme)) utilruntime.Must(scheme.SetVersionPriority(kubeschedulerconfigv1alpha1.SchemeGroupVersion)) } diff --git a/pkg/scheduler/api/compatibility/BUILD b/pkg/scheduler/apis/config/testing/BUILD similarity index 95% rename from pkg/scheduler/api/compatibility/BUILD rename to pkg/scheduler/apis/config/testing/BUILD index 107f218dcf5..f507fddd4dd 100644 --- a/pkg/scheduler/api/compatibility/BUILD +++ b/pkg/scheduler/apis/config/testing/BUILD @@ -9,11 +9,11 @@ go_test( "//pkg/scheduler:go_default_library", "//pkg/scheduler/algorithmprovider:go_default_library", "//pkg/scheduler/algorithmprovider/defaults:go_default_library", - "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/apis/config:go_default_library", "//pkg/scheduler/core:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library", diff --git a/pkg/scheduler/api/compatibility/compatibility_test.go b/pkg/scheduler/apis/config/testing/compatibility_test.go similarity index 93% rename from pkg/scheduler/api/compatibility/compatibility_test.go rename to pkg/scheduler/apis/config/testing/compatibility_test.go index f3ebc2a1e6b..94db0feb8d7 100644 --- a/pkg/scheduler/api/compatibility/compatibility_test.go +++ b/pkg/scheduler/apis/config/testing/compatibility_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package compatibility +package testing import ( "testing" @@ -34,9 +34,7 @@ import ( "k8s.io/kubernetes/pkg/scheduler" "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" - schedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/core" ) @@ -46,8 +44,8 @@ type testCase struct { featureGates map[featuregate.Feature]bool wantPredicates sets.String wantPrioritizers sets.String - wantPlugins map[string][]kubeschedulerconfig.Plugin - wantExtenders []schedulerapi.ExtenderConfig + wantPlugins map[string][]config.Plugin + wantExtenders []config.Extender } func TestCompatibility_v1_Scheduler(t *testing.T) { @@ -66,7 +64,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "priorities": [ ] }`, - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeResourcesFit"}, @@ -107,7 +105,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "TestServiceAntiAffinity", "TestLabelPreference", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeAffinity"}, @@ -155,7 +153,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "TestServiceAntiAffinity", "TestLabelPreference", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeName"}, @@ -211,7 +209,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "TestServiceAntiAffinity", "TestLabelPreference", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeName"}, @@ -275,7 +273,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "SelectorSpreadPriority", "InterPodAffinityPriority", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeName"}, @@ -343,7 +341,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "SelectorSpreadPriority", "InterPodAffinityPriority", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeName"}, @@ -422,7 +420,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "SelectorSpreadPriority", "InterPodAffinityPriority", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeName"}, @@ -448,14 +446,14 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "TaintToleration", Weight: 2}, }, }, - wantExtenders: []schedulerapi.ExtenderConfig{{ + wantExtenders: []config.Extender{{ URLPrefix: "/prefix", FilterVerb: "filter", PrioritizeVerb: "prioritize", Weight: 1, BindVerb: "bind", // 1.7 was missing json tags on the BindVerb field and required "BindVerb" EnableHTTPS: true, - TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, + TLSConfig: &config.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, }}, @@ -512,7 +510,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "SelectorSpreadPriority", "InterPodAffinityPriority", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeName"}, @@ -538,14 +536,14 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "TaintToleration", Weight: 2}, }, }, - wantExtenders: []schedulerapi.ExtenderConfig{{ + wantExtenders: []config.Extender{{ URLPrefix: "/prefix", FilterVerb: "filter", PrioritizeVerb: "prioritize", Weight: 1, BindVerb: "bind", // 1.8 became case-insensitive and tolerated "bindVerb" EnableHTTPS: true, - TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, + TLSConfig: &config.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, }}, @@ -603,7 +601,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "SelectorSpreadPriority", "InterPodAffinityPriority", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeName"}, @@ -630,14 +628,14 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "TaintToleration", Weight: 2}, }, }, - wantExtenders: []schedulerapi.ExtenderConfig{{ + wantExtenders: []config.Extender{{ URLPrefix: "/prefix", FilterVerb: "filter", PrioritizeVerb: "prioritize", Weight: 1, BindVerb: "bind", // 1.9 was case-insensitive and tolerated "bindVerb" EnableHTTPS: true, - TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, + TLSConfig: &config.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, }}, @@ -698,7 +696,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "SelectorSpreadPriority", "InterPodAffinityPriority", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeName"}, @@ -725,17 +723,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "TaintToleration", Weight: 2}, }, }, - wantExtenders: []schedulerapi.ExtenderConfig{{ + wantExtenders: []config.Extender{{ URLPrefix: "/prefix", FilterVerb: "filter", PrioritizeVerb: "prioritize", Weight: 1, BindVerb: "bind", // 1.10 was case-insensitive and tolerated "bindVerb" EnableHTTPS: true, - TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, + TLSConfig: &config.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, - ManagedResources: []schedulerapi.ExtenderManagedResource{{Name: v1.ResourceName("example.com/foo"), IgnoredByScheduler: true}}, + ManagedResources: []config.ExtenderManagedResource{{Name: "example.com/foo", IgnoredByScheduler: true}}, Ignorable: true, }}, }, @@ -805,7 +803,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "SelectorSpreadPriority", "InterPodAffinityPriority", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeName"}, @@ -833,17 +831,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "TaintToleration", Weight: 2}, }, }, - wantExtenders: []schedulerapi.ExtenderConfig{{ + wantExtenders: []config.Extender{{ URLPrefix: "/prefix", FilterVerb: "filter", PrioritizeVerb: "prioritize", Weight: 1, BindVerb: "bind", // 1.11 restored case-sensitivity, but allowed either "BindVerb" or "bindVerb" EnableHTTPS: true, - TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, + TLSConfig: &config.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, - ManagedResources: []schedulerapi.ExtenderManagedResource{{Name: v1.ResourceName("example.com/foo"), IgnoredByScheduler: true}}, + ManagedResources: []config.ExtenderManagedResource{{Name: "example.com/foo", IgnoredByScheduler: true}}, Ignorable: true, }}, }, @@ -914,7 +912,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "SelectorSpreadPriority", "InterPodAffinityPriority", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeName"}, @@ -943,17 +941,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "TaintToleration", Weight: 2}, }, }, - wantExtenders: []schedulerapi.ExtenderConfig{{ + wantExtenders: []config.Extender{{ URLPrefix: "/prefix", FilterVerb: "filter", PrioritizeVerb: "prioritize", Weight: 1, BindVerb: "bind", // 1.11 restored case-sensitivity, but allowed either "BindVerb" or "bindVerb" EnableHTTPS: true, - TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, + TLSConfig: &config.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, - ManagedResources: []schedulerapi.ExtenderManagedResource{{Name: v1.ResourceName("example.com/foo"), IgnoredByScheduler: true}}, + ManagedResources: []config.ExtenderManagedResource{{Name: "example.com/foo", IgnoredByScheduler: true}}, Ignorable: true, }}, }, @@ -1023,7 +1021,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "SelectorSpreadPriority", "InterPodAffinityPriority", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeName"}, @@ -1053,17 +1051,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "TaintToleration", Weight: 2}, }, }, - wantExtenders: []schedulerapi.ExtenderConfig{{ + wantExtenders: []config.Extender{{ URLPrefix: "/prefix", FilterVerb: "filter", PrioritizeVerb: "prioritize", Weight: 1, BindVerb: "bind", // 1.11 restored case-sensitivity, but allowed either "BindVerb" or "bindVerb" EnableHTTPS: true, - TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, + TLSConfig: &config.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, - ManagedResources: []schedulerapi.ExtenderManagedResource{{Name: v1.ResourceName("example.com/foo"), IgnoredByScheduler: true}}, + ManagedResources: []config.ExtenderManagedResource{{Name: "example.com/foo", IgnoredByScheduler: true}}, Ignorable: true, }}, }, @@ -1137,7 +1135,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { "SelectorSpreadPriority", "InterPodAffinityPriority", ), - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "NodeName"}, @@ -1167,17 +1165,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "TaintToleration", Weight: 2}, }, }, - wantExtenders: []schedulerapi.ExtenderConfig{{ + wantExtenders: []config.Extender{{ URLPrefix: "/prefix", FilterVerb: "filter", PrioritizeVerb: "prioritize", Weight: 1, BindVerb: "bind", // 1.11 restored case-sensitivity, but allowed either "BindVerb" or "bindVerb" EnableHTTPS: true, - TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, + TLSConfig: &config.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, - ManagedResources: []schedulerapi.ExtenderManagedResource{{Name: v1.ResourceName("example.com/foo"), IgnoredByScheduler: true}}, + ManagedResources: []config.ExtenderManagedResource{{Name: "example.com/foo", IgnoredByScheduler: true}}, Ignorable: true, }}, }, @@ -1196,7 +1194,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { featureGates: map[featuregate.Feature]bool{ features.EvenPodsSpread: true, }, - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "TaintToleration"}, @@ -1222,7 +1220,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { featureGates: map[featuregate.Feature]bool{ features.AttachVolumeLimit: false, }, - wantPlugins: map[string][]kubeschedulerconfig.Plugin{ + wantPlugins: map[string][]config.Plugin{ "FilterPlugin": { {Name: "NodeUnschedulable"}, {Name: "TaintToleration"}, @@ -1279,12 +1277,12 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { } policyConfigMap := v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "scheduler-custom-policy-config"}, - Data: map[string]string{schedulerconfig.SchedulerPolicyConfigMapKey: tc.JSON}, + Data: map[string]string{config.SchedulerPolicyConfigMapKey: tc.JSON}, } client := fake.NewSimpleClientset(&policyConfigMap) - algorithmSrc := schedulerconfig.SchedulerAlgorithmSource{ - Policy: &schedulerconfig.SchedulerPolicySource{ - ConfigMap: &kubeschedulerconfig.SchedulerPolicyConfigMapSource{ + algorithmSrc := config.SchedulerAlgorithmSource{ + Policy: &config.SchedulerPolicySource{ + ConfigMap: &config.SchedulerPolicyConfigMapSource{ Namespace: policyConfigMap.Namespace, Name: policyConfigMap.Name, }, @@ -1365,7 +1363,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { } } -func pluginsToStringSet(plugins []kubeschedulerconfig.Plugin) sets.String { +func pluginsToStringSet(plugins []config.Plugin) sets.String { s := sets.NewString() for _, p := range plugins { s.Insert(p.Name) diff --git a/pkg/scheduler/apis/config/testing/policy_test.go b/pkg/scheduler/apis/config/testing/policy_test.go new file mode 100644 index 00000000000..63e8123d3ae --- /dev/null +++ b/pkg/scheduler/apis/config/testing/policy_test.go @@ -0,0 +1,108 @@ +/* +Copyright 2019 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 testing + +import ( + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + "k8s.io/apimachinery/pkg/runtime" + + "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" +) + +const ( + policyTemplate = ` +apiVersion: %s +kind: Policy +extenders: +- urlPrefix: http://localhost:8888/ + filterVerb: filter + prioritizeVerb: prioritize + weight: 1 + enableHttps: false +` +) + +func TestSchedulerPolicy(t *testing.T) { + expected := &config.Policy{ + Extenders: []config.Extender{ + { + URLPrefix: "http://localhost:8888/", + FilterVerb: "filter", + PrioritizeVerb: "prioritize", + Weight: 1, + EnableHTTPS: false, + }, + }, + } + testcases := []struct { + name string + apiVersion string + expectError bool + expectedObj *config.Policy + }{ + // verifies if a Policy YAML with apiVersion 'v1' can be + // serialized into an unversioned Policy object. + { + name: "legacy v1", + apiVersion: "v1", + expectError: false, + expectedObj: expected, + }, + // verifies if a Policy YAML with apiVersion 'kubescheduler.config.k8s.io/v1' + // can be serialized into an unversioned Policy object. + { + name: "v1", + apiVersion: "kubescheduler.config.k8s.io/v1", + expectError: false, + expectedObj: expected, + }, + // ensures unknown version throws a parsing error. + { + name: "unknown version", + apiVersion: "kubescheduler.config.k8s.io/vunknown", + expectError: true, + }, + } + for _, tt := range testcases { + t.Run(tt.name, func(t *testing.T) { + policyStr := fmt.Sprintf(policyTemplate, tt.apiVersion) + got, err := loadPolicy([]byte(policyStr)) + if (err != nil) != tt.expectError { + t.Fatalf("Error while parsing Policy. expectErr=%v, but got=%v.", tt.expectError, err) + } + + if !tt.expectError { + if diff := cmp.Diff(tt.expectedObj, got); diff != "" { + t.Errorf("Unexpected policy diff (-want, +got): %s", diff) + } + } + }) + } +} + +// loadPolicy decodes data as a Policy object. +func loadPolicy(data []byte) (*config.Policy, error) { + policy := config.Policy{} + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), data, &policy); err != nil { + return nil, err + } + return &policy, nil +} diff --git a/pkg/scheduler/apis/config/types.go b/pkg/scheduler/apis/config/types.go index 7b8c0a33047..87e7c3603e3 100644 --- a/pkg/scheduler/apis/config/types.go +++ b/pkg/scheduler/apis/config/types.go @@ -17,6 +17,8 @@ limitations under the License. package config import ( + "math" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" componentbaseconfig "k8s.io/component-base/config" @@ -220,9 +222,23 @@ type PluginConfig struct { Args runtime.Unknown } -/////////////////////////////////////////////////////////////////////////////// -// NOTE: The following methods are intentionally left out of the staging mirror. -/////////////////////////////////////////////////////////////////////////////// +/* + * NOTE: The following variables and methods are intentionally left out of the staging mirror. + */ +const ( + // DefaultPercentageOfNodesToScore defines the percentage of nodes of all nodes + // that once found feasible, the scheduler stops looking for more nodes. + DefaultPercentageOfNodesToScore = 50 + + // MaxCustomPriorityScore is the max score UtilizationShapePoint expects. + MaxCustomPriorityScore int64 = 10 + + // MaxTotalScore is the maximum total score. + MaxTotalScore int64 = math.MaxInt64 + + // MaxWeight defines the max weight value allowed for custom PriorityPolicy + MaxWeight = MaxTotalScore / MaxCustomPriorityScore +) func appendPluginSet(dst *PluginSet, src *PluginSet) *PluginSet { if dst == nil { diff --git a/pkg/scheduler/api/v1/doc.go b/pkg/scheduler/apis/config/v1/doc.go similarity index 62% rename from pkg/scheduler/api/v1/doc.go rename to pkg/scheduler/apis/config/v1/doc.go index 3386c4d8d21..21bfc073adb 100644 --- a/pkg/scheduler/api/v1/doc.go +++ b/pkg/scheduler/apis/config/v1/doc.go @@ -15,6 +15,10 @@ 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/v1 +// +k8s:defaulter-gen=TypeMeta +// +k8s:defaulter-gen-input=../../../../../vendor/k8s.io/kube-scheduler/config/v1 +// +groupName=kubescheduler.config.k8s.io -// Package v1 contains scheduler API objects. -package v1 // import "k8s.io/kubernetes/pkg/scheduler/api/v1" +package v1 // import "k8s.io/kubernetes/pkg/scheduler/apis/config/v1" diff --git a/pkg/scheduler/api/v1/register.go b/pkg/scheduler/apis/config/v1/register.go similarity index 55% rename from pkg/scheduler/api/v1/register.go rename to pkg/scheduler/apis/config/v1/register.go index 504de9c7672..d5deb35604b 100644 --- a/pkg/scheduler/api/v1/register.go +++ b/pkg/scheduler/apis/config/v1/register.go @@ -17,30 +17,21 @@ limitations under the License. package v1 import ( - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + kubeschedulerconfigv1 "k8s.io/kube-scheduler/config/v1" ) -// SchemeGroupVersion is group version used to register these objects -// TODO this should be in the "scheduler" group -var SchemeGroupVersion = schema.GroupVersion{Group: "", Version: "v1"} +// GroupName is the group name used in this package +const GroupName = "kubescheduler.config.k8s.io" -func init() { - if err := addKnownTypes(schedulerapi.Scheme); err != nil { - // Programmer error. - panic(err) - } -} +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} var ( - // TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api. - // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. - - // SchemeBuilder is a v1 api scheme builder. - SchemeBuilder runtime.SchemeBuilder - localSchemeBuilder = &SchemeBuilder - // AddToScheme is used to add stored functions to scheme. + // localSchemeBuilder extends the SchemeBuilder instance with the external types. In this package, + // defaulting and conversion init funcs are registered as well. + localSchemeBuilder = &kubeschedulerconfigv1.SchemeBuilder + // AddToScheme is a global function that registers this API group & version to a scheme AddToScheme = localSchemeBuilder.AddToScheme ) @@ -48,12 +39,5 @@ 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(addKnownTypes) -} - -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(SchemeGroupVersion, - &Policy{}, - ) - return nil + localSchemeBuilder.Register(RegisterDefaults) } diff --git a/pkg/scheduler/apis/config/validation/validation.go b/pkg/scheduler/apis/config/validation/validation.go index 3ef80bb8bfd..50bab297b7a 100644 --- a/pkg/scheduler/apis/config/validation/validation.go +++ b/pkg/scheduler/apis/config/validation/validation.go @@ -17,9 +17,16 @@ limitations under the License. package validation import ( + "errors" + "fmt" + + v1 "k8s.io/api/core/v1" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" componentbasevalidation "k8s.io/component-base/config/validation" + v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/scheduler/apis/config" ) @@ -71,3 +78,106 @@ func ValidateKubeSchedulerLeaderElectionConfiguration(cc *config.KubeSchedulerLe allErrs = append(allErrs, componentbasevalidation.ValidateLeaderElectionConfiguration(&cc.LeaderElectionConfiguration, field.NewPath("leaderElectionConfiguration"))...) return allErrs } + +// ValidatePolicy checks for errors in the Config +// It does not return early so that it can find as many errors as possible +func ValidatePolicy(policy config.Policy) error { + var validationErrors []error + + priorities := make(map[string]config.PriorityPolicy, len(policy.Priorities)) + for _, priority := range policy.Priorities { + if priority.Weight <= 0 || priority.Weight >= config.MaxWeight { + validationErrors = append(validationErrors, fmt.Errorf("Priority %s should have a positive weight applied to it or it has overflown", priority.Name)) + } + + validationErrors = append(validationErrors, validatePriorityRedeclared(priorities, priority)) + } + + predicates := make(map[string]config.PredicatePolicy, len(policy.Predicates)) + for _, predicate := range policy.Predicates { + validationErrors = append(validationErrors, validatePredicateRedeclared(predicates, predicate)) + } + + binders := 0 + extenderManagedResources := sets.NewString() + for _, extender := range policy.Extenders { + if len(extender.PrioritizeVerb) > 0 && extender.Weight <= 0 { + validationErrors = append(validationErrors, fmt.Errorf("Priority for extender %s should have a positive weight applied to it", extender.URLPrefix)) + } + if extender.BindVerb != "" { + binders++ + } + for _, resource := range extender.ManagedResources { + errs := validateExtendedResourceName(v1.ResourceName(resource.Name)) + if len(errs) != 0 { + validationErrors = append(validationErrors, errs...) + } + if extenderManagedResources.Has(resource.Name) { + validationErrors = append(validationErrors, fmt.Errorf("Duplicate extender managed resource name %s", string(resource.Name))) + } + extenderManagedResources.Insert(resource.Name) + } + } + if binders > 1 { + validationErrors = append(validationErrors, fmt.Errorf("Only one extender can implement bind, found %v", binders)) + } + return utilerrors.NewAggregate(validationErrors) +} + +// validatePriorityRedeclared checks if any custom priorities have been declared multiple times in the policy config +// by examining the specified priority arguments +func validatePriorityRedeclared(priorities map[string]config.PriorityPolicy, priority config.PriorityPolicy) error { + var priorityType string + if priority.Argument != nil { + if priority.Argument.LabelPreference != nil { + priorityType = "LabelPreference" + } else if priority.Argument.RequestedToCapacityRatioArguments != nil { + priorityType = "RequestedToCapacityRatioArguments" + } else if priority.Argument.ServiceAntiAffinity != nil { + priorityType = "ServiceAntiAffinity" + } else { + return fmt.Errorf("No priority arguments set for priority %s", priority.Name) + } + if existing, alreadyDeclared := priorities[priorityType]; alreadyDeclared { + return fmt.Errorf("Priority '%s' redeclares custom priority '%s', from:'%s'", priority.Name, priorityType, existing.Name) + } + priorities[priorityType] = priority + } + return nil +} + +// validatePredicateRedeclared checks if any custom predicates have been declared multiple times in the policy config +// by examining the specified predicate arguments +func validatePredicateRedeclared(predicates map[string]config.PredicatePolicy, predicate config.PredicatePolicy) error { + var predicateType string + if predicate.Argument != nil { + if predicate.Argument.LabelsPresence != nil { + predicateType = "LabelsPresence" + } else if predicate.Argument.ServiceAffinity != nil { + predicateType = "ServiceAffinity" + } else { + return fmt.Errorf("No priority arguments set for priority %s", predicate.Name) + } + if existing, alreadyDeclared := predicates[predicateType]; alreadyDeclared { + return fmt.Errorf("Predicate '%s' redeclares custom predicate '%s', from:'%s'", predicate.Name, predicateType, existing.Name) + } + predicates[predicateType] = predicate + } + return nil +} + +// validateExtendedResourceName checks whether the specified name is a valid +// extended resource name. +func validateExtendedResourceName(name v1.ResourceName) []error { + var validationErrors []error + for _, msg := range validation.IsQualifiedName(string(name)) { + validationErrors = append(validationErrors, errors.New(msg)) + } + if len(validationErrors) != 0 { + return validationErrors + } + if !v1helper.IsExtendedResourceName(name) { + validationErrors = append(validationErrors, fmt.Errorf("%s is an invalid extended resource name", name)) + } + return validationErrors +} diff --git a/pkg/scheduler/apis/config/validation/validation_test.go b/pkg/scheduler/apis/config/validation/validation_test.go index 698b5bbbfc5..90226b335b4 100644 --- a/pkg/scheduler/apis/config/validation/validation_test.go +++ b/pkg/scheduler/apis/config/validation/validation_test.go @@ -17,6 +17,8 @@ limitations under the License. package validation import ( + "errors" + "fmt" "testing" "time" @@ -159,3 +161,112 @@ func TestValidateKubeSchedulerConfiguration(t *testing.T) { } } } + +func TestValidatePolicy(t *testing.T) { + tests := []struct { + policy config.Policy + expected error + name string + }{ + { + name: "no weight defined in policy", + policy: config.Policy{Priorities: []config.PriorityPolicy{{Name: "NoWeightPriority"}}}, + expected: errors.New("Priority NoWeightPriority should have a positive weight applied to it or it has overflown"), + }, + { + name: "policy weight is not positive", + policy: config.Policy{Priorities: []config.PriorityPolicy{{Name: "NoWeightPriority", Weight: 0}}}, + expected: errors.New("Priority NoWeightPriority should have a positive weight applied to it or it has overflown"), + }, + { + name: "valid weight priority", + policy: config.Policy{Priorities: []config.PriorityPolicy{{Name: "WeightPriority", Weight: 2}}}, + expected: nil, + }, + { + name: "invalid negative weight policy", + policy: config.Policy{Priorities: []config.PriorityPolicy{{Name: "WeightPriority", Weight: -2}}}, + expected: errors.New("Priority WeightPriority should have a positive weight applied to it or it has overflown"), + }, + { + name: "policy weight exceeds maximum", + policy: config.Policy{Priorities: []config.PriorityPolicy{{Name: "WeightPriority", Weight: config.MaxWeight}}}, + expected: errors.New("Priority WeightPriority should have a positive weight applied to it or it has overflown"), + }, + { + name: "valid weight in policy extender config", + policy: config.Policy{Extenders: []config.Extender{{URLPrefix: "http://127.0.0.1:8081/extender", PrioritizeVerb: "prioritize", Weight: 2}}}, + expected: nil, + }, + { + name: "invalid negative weight in policy extender config", + policy: config.Policy{Extenders: []config.Extender{{URLPrefix: "http://127.0.0.1:8081/extender", PrioritizeVerb: "prioritize", Weight: -2}}}, + expected: errors.New("Priority for extender http://127.0.0.1:8081/extender should have a positive weight applied to it"), + }, + { + name: "valid filter verb and url prefix", + policy: config.Policy{Extenders: []config.Extender{{URLPrefix: "http://127.0.0.1:8081/extender", FilterVerb: "filter"}}}, + expected: nil, + }, + { + name: "valid preemt verb and urlprefix", + policy: config.Policy{Extenders: []config.Extender{{URLPrefix: "http://127.0.0.1:8081/extender", PreemptVerb: "preempt"}}}, + expected: nil, + }, + { + name: "invalid multiple extenders", + policy: config.Policy{ + Extenders: []config.Extender{ + {URLPrefix: "http://127.0.0.1:8081/extender", BindVerb: "bind"}, + {URLPrefix: "http://127.0.0.1:8082/extender", BindVerb: "bind"}, + }}, + expected: errors.New("Only one extender can implement bind, found 2"), + }, + { + name: "invalid duplicate extender resource name", + policy: config.Policy{ + Extenders: []config.Extender{ + {URLPrefix: "http://127.0.0.1:8081/extender", ManagedResources: []config.ExtenderManagedResource{{Name: "foo.com/bar"}}}, + {URLPrefix: "http://127.0.0.1:8082/extender", BindVerb: "bind", ManagedResources: []config.ExtenderManagedResource{{Name: "foo.com/bar"}}}, + }}, + expected: errors.New("Duplicate extender managed resource name foo.com/bar"), + }, + { + name: "invalid extended resource name", + policy: config.Policy{ + Extenders: []config.Extender{ + {URLPrefix: "http://127.0.0.1:8081/extender", ManagedResources: []config.ExtenderManagedResource{{Name: "kubernetes.io/foo"}}}, + }}, + expected: errors.New("kubernetes.io/foo is an invalid extended resource name"), + }, + { + name: "invalid redeclared custom predicate", + policy: config.Policy{ + Predicates: []config.PredicatePolicy{ + {Name: "customPredicate1", Argument: &config.PredicateArgument{ServiceAffinity: &config.ServiceAffinity{Labels: []string{"label1"}}}}, + {Name: "customPredicate2", Argument: &config.PredicateArgument{ServiceAffinity: &config.ServiceAffinity{Labels: []string{"label2"}}}}, + }, + }, + expected: errors.New("Predicate 'customPredicate2' redeclares custom predicate 'ServiceAffinity', from:'customPredicate1'"), + }, + { + name: "invalid redeclared custom priority", + policy: config.Policy{ + Priorities: []config.PriorityPolicy{ + {Name: "customPriority1", Weight: 1, Argument: &config.PriorityArgument{ServiceAntiAffinity: &config.ServiceAntiAffinity{Label: "label1"}}}, + {Name: "customPriority2", Weight: 1, Argument: &config.PriorityArgument{ServiceAntiAffinity: &config.ServiceAntiAffinity{Label: "label2"}}}, + }, + }, + expected: errors.New("Priority 'customPriority2' redeclares custom priority 'ServiceAntiAffinity', from:'customPriority1'"), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actual := ValidatePolicy(test.policy) + if fmt.Sprint(test.expected) != fmt.Sprint(actual) { + t.Errorf("expected: %s, actual: %s", test.expected, actual) + } + }) + } +} diff --git a/pkg/scheduler/core/extender.go b/pkg/scheduler/core/extender.go index e47dd834e55..81fe0f66ea0 100644 --- a/pkg/scheduler/core/extender.go +++ b/pkg/scheduler/core/extender.go @@ -29,7 +29,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" restclient "k8s.io/client-go/rest" "k8s.io/kubernetes/pkg/scheduler/algorithm" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" extenderv1 "k8s.io/kubernetes/pkg/scheduler/apis/extender/v1" schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) @@ -53,7 +53,7 @@ type HTTPExtender struct { ignorable bool } -func makeTransport(config *schedulerapi.ExtenderConfig) (http.RoundTripper, error) { +func makeTransport(config *schedulerapi.Extender) (http.RoundTripper, error) { var cfg restclient.Config if config.TLSConfig != nil { cfg.TLSClientConfig.Insecure = config.TLSConfig.Insecure @@ -84,7 +84,7 @@ func makeTransport(config *schedulerapi.ExtenderConfig) (http.RoundTripper, erro } // NewHTTPExtender creates an HTTPExtender object. -func NewHTTPExtender(config *schedulerapi.ExtenderConfig) (algorithm.SchedulerExtender, error) { +func NewHTTPExtender(config *schedulerapi.Extender) (algorithm.SchedulerExtender, error) { if config.HTTPTimeout.Nanoseconds() == 0 { config.HTTPTimeout = time.Duration(DefaultExtenderTimeout) } diff --git a/pkg/scheduler/core/extender_test.go b/pkg/scheduler/core/extender_test.go index 92376c537b9..4ec7504840a 100644 --- a/pkg/scheduler/core/extender_test.go +++ b/pkg/scheduler/core/extender_test.go @@ -35,7 +35,7 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" extenderv1 "k8s.io/kubernetes/pkg/scheduler/apis/extender/v1" framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" internalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" diff --git a/pkg/scheduler/core/generic_scheduler.go b/pkg/scheduler/core/generic_scheduler.go index 2b7286cac7e..2e075a1ac93 100644 --- a/pkg/scheduler/core/generic_scheduler.go +++ b/pkg/scheduler/core/generic_scheduler.go @@ -41,9 +41,9 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" extenderv1 "k8s.io/kubernetes/pkg/scheduler/apis/extender/v1" - migration "k8s.io/kubernetes/pkg/scheduler/framework/plugins/migration" + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/migration" framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" internalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" internalqueue "k8s.io/kubernetes/pkg/scheduler/internal/queue" diff --git a/pkg/scheduler/core/generic_scheduler_test.go b/pkg/scheduler/core/generic_scheduler_test.go index 914b2f1f8eb..ed5b54b9ba7 100644 --- a/pkg/scheduler/core/generic_scheduler_test.go +++ b/pkg/scheduler/core/generic_scheduler_test.go @@ -41,8 +41,7 @@ import ( algorithmpredicates "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" extenderv1 "k8s.io/kubernetes/pkg/scheduler/apis/extender/v1" framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" internalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" @@ -144,7 +143,7 @@ func getNodeReducePriority(pod *v1.Pod, meta interface{}, sharedLister scheduler // EmptyPluginRegistry is a test plugin set used by the default scheduler. var EmptyPluginRegistry = framework.Registry{} -var emptyFramework, _ = framework.NewFramework(EmptyPluginRegistry, nil, []schedulerconfig.PluginConfig{}) +var emptyFramework, _ = framework.NewFramework(EmptyPluginRegistry, nil, []schedulerapi.PluginConfig{}) // FakeFilterPlugin is a test filter plugin used by default scheduler. type FakeFilterPlugin struct { @@ -265,15 +264,15 @@ func TestGenericScheduler(t *testing.T) { filterPlugin := &FakeFilterPlugin{} filterPluginRegistry := framework.Registry{filterPlugin.Name(): newPlugin(filterPlugin)} - filterFramework, err := framework.NewFramework(filterPluginRegistry, &schedulerconfig.Plugins{ - Filter: &schedulerconfig.PluginSet{ - Enabled: []schedulerconfig.Plugin{ + filterFramework, err := framework.NewFramework(filterPluginRegistry, &schedulerapi.Plugins{ + Filter: &schedulerapi.PluginSet{ + Enabled: []schedulerapi.Plugin{ { Name: filterPlugin.Name(), }, }, }, - }, []schedulerconfig.PluginConfig{}) + }, []schedulerapi.PluginConfig{}) if err != nil { t.Errorf("Unexpected error when initialize scheduling framework, err :%v", err.Error()) } @@ -1153,15 +1152,15 @@ func TestSelectNodesForPreemption(t *testing.T) { filterPlugin := &FakeFilterPlugin{} filterPluginRegistry := framework.Registry{filterPlugin.Name(): newPlugin(filterPlugin)} - filterFramework, err := framework.NewFramework(filterPluginRegistry, &schedulerconfig.Plugins{ - Filter: &schedulerconfig.PluginSet{ - Enabled: []schedulerconfig.Plugin{ + filterFramework, err := framework.NewFramework(filterPluginRegistry, &schedulerapi.Plugins{ + Filter: &schedulerapi.PluginSet{ + Enabled: []schedulerapi.Plugin{ { Name: filterPlugin.Name(), }, }, }, - }, []schedulerconfig.PluginConfig{}) + }, []schedulerapi.PluginConfig{}) if err != nil { t.Errorf("Unexpected error when initialize scheduling framework, err :%v", err.Error()) } @@ -1673,7 +1672,7 @@ func TestPickOneNodeForPreemption(t *testing.T) { nodes = append(nodes, makeNode(n, priorityutil.DefaultMilliCPURequest*5, priorityutil.DefaultMemoryRequest*5)) } snapshot := nodeinfosnapshot.NewSnapshot(test.pods, nodes) - fwk, _ := framework.NewFramework(EmptyPluginRegistry, nil, []schedulerconfig.PluginConfig{}, framework.WithNodeInfoSnapshot(snapshot)) + fwk, _ := framework.NewFramework(EmptyPluginRegistry, nil, []schedulerapi.PluginConfig{}, framework.WithNodeInfoSnapshot(snapshot)) g := &genericScheduler{ framework: fwk, diff --git a/pkg/scheduler/factory.go b/pkg/scheduler/factory.go index 623d4a57de6..5a791b3abc8 100644 --- a/pkg/scheduler/factory.go +++ b/pkg/scheduler/factory.go @@ -48,9 +48,8 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - "k8s.io/kubernetes/pkg/scheduler/api/validation" - "k8s.io/kubernetes/pkg/scheduler/apis/config" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/kubernetes/pkg/scheduler/apis/config/validation" "k8s.io/kubernetes/pkg/scheduler/core" "k8s.io/kubernetes/pkg/scheduler/framework/plugins" framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" @@ -107,8 +106,8 @@ type Config struct { SchedulingQueue internalqueue.SchedulingQueue // The final configuration of the framework. - Plugins config.Plugins - PluginConfig []config.PluginConfig + Plugins schedulerapi.Plugins + PluginConfig []schedulerapi.PluginConfig } // Configurator defines I/O, caching, and other functionality needed to @@ -173,8 +172,8 @@ type Configurator struct { // framework configuration arguments. registry framework.Registry - plugins *config.Plugins - pluginConfig []config.PluginConfig + plugins *schedulerapi.Plugins + pluginConfig []schedulerapi.PluginConfig pluginConfigProducerRegistry *plugins.ConfigProducerRegistry nodeInfoSnapshot *nodeinfosnapshot.Snapshot @@ -207,8 +206,8 @@ type ConfigFactoryArgs struct { PodMaxBackoffSeconds int64 StopCh <-chan struct{} Registry framework.Registry - Plugins *config.Plugins - PluginConfig []config.PluginConfig + Plugins *schedulerapi.Plugins + PluginConfig []schedulerapi.PluginConfig PluginConfigProducerRegistry *plugins.ConfigProducerRegistry } @@ -346,12 +345,12 @@ func (c *Configurator) CreateFromConfig(policy schedulerapi.Policy) (*Config, er } var extenders []algorithm.SchedulerExtender - if len(policy.ExtenderConfigs) != 0 { + if len(policy.Extenders) != 0 { ignoredExtendedResources := sets.NewString() var ignorableExtenders []algorithm.SchedulerExtender - for ii := range policy.ExtenderConfigs { - klog.V(2).Infof("Creating extender with config %+v", policy.ExtenderConfigs[ii]) - extender, err := core.NewHTTPExtender(&policy.ExtenderConfigs[ii]) + for ii := range policy.Extenders { + klog.V(2).Infof("Creating extender with config %+v", policy.Extenders[ii]) + extender, err := core.NewHTTPExtender(&policy.Extenders[ii]) if err != nil { return nil, err } @@ -360,7 +359,7 @@ func (c *Configurator) CreateFromConfig(policy schedulerapi.Policy) (*Config, er } else { ignorableExtenders = append(ignorableExtenders, extender) } - for _, r := range policy.ExtenderConfigs[ii].ManagedResources { + for _, r := range policy.Extenders[ii].ManagedResources { if r.IgnoredByScheduler { ignoredExtendedResources.Insert(string(r.Name)) } @@ -414,11 +413,11 @@ func (c *Configurator) CreateFromKeys(predicateKeys, priorityKeys sets.String, e // Combine all framework configurations. If this results in any duplication, framework // instantiation should fail. - var plugins config.Plugins + var plugins schedulerapi.Plugins plugins.Append(pluginsForPredicates) plugins.Append(pluginsForPriorities) plugins.Append(c.plugins) - var pluginConfig []config.PluginConfig + var pluginConfig []schedulerapi.PluginConfig pluginConfig = append(pluginConfig, pluginConfigForPredicates...) pluginConfig = append(pluginConfig, pluginConfigForPriorities...) pluginConfig = append(pluginConfig, c.pluginConfig...) @@ -505,7 +504,7 @@ func getBinderFunc(client clientset.Interface, extenders []algorithm.SchedulerEx // getPriorityConfigs returns priorities configuration: ones that will run as priorities and ones that will run // as framework plugins. Specifically, a priority will run as a framework plugin if a plugin config producer was // registered for that priority. -func (c *Configurator) getPriorityConfigs(priorityKeys sets.String) ([]priorities.PriorityConfig, *config.Plugins, []config.PluginConfig, error) { +func (c *Configurator) getPriorityConfigs(priorityKeys sets.String) ([]priorities.PriorityConfig, *schedulerapi.Plugins, []schedulerapi.PluginConfig, error) { allPriorityConfigs, err := getPriorityFunctionConfigs(priorityKeys, *c.factoryArgs) if err != nil { return nil, nil, nil, err @@ -516,8 +515,8 @@ func (c *Configurator) getPriorityConfigs(priorityKeys sets.String) ([]prioritie } var priorityConfigs []priorities.PriorityConfig - var plugins config.Plugins - var pluginConfig []config.PluginConfig + var plugins schedulerapi.Plugins + var pluginConfig []schedulerapi.PluginConfig frameworkConfigProducers := c.pluginConfigProducerRegistry.PriorityToConfigProducer for _, p := range allPriorityConfigs { if producer, exist := frameworkConfigProducers[p.Name]; exist { @@ -544,7 +543,7 @@ func (c *Configurator) GetPredicateMetadataProducer() (predicates.PredicateMetad // registered for that predicate. // Note that the framework executes plugins according to their order in the Plugins list, and so predicates run as plugins // are added to the Plugins list according to the order specified in predicates.Ordering(). -func (c *Configurator) getPredicateConfigs(predicateKeys sets.String) (map[string]predicates.FitPredicate, *config.Plugins, []config.PluginConfig, error) { +func (c *Configurator) getPredicateConfigs(predicateKeys sets.String) (map[string]predicates.FitPredicate, *schedulerapi.Plugins, []schedulerapi.PluginConfig, error) { allFitPredicates, err := getFitPredicateFunctions(predicateKeys, *c.factoryArgs) if err != nil { return nil, nil, nil, err @@ -570,8 +569,8 @@ func (c *Configurator) getPredicateConfigs(predicateKeys sets.String) (map[strin // Second, create the framework plugin configurations, and place them in the order // that the corresponding predicates were supposed to run. - var plugins config.Plugins - var pluginConfig []config.PluginConfig + var plugins schedulerapi.Plugins + var pluginConfig []schedulerapi.PluginConfig for _, predicateKey := range predicates.Ordering() { if asPlugins.Has(predicateKey) { diff --git a/pkg/scheduler/factory_test.go b/pkg/scheduler/factory_test.go index 74400da20c6..eae6cf2b0f4 100644 --- a/pkg/scheduler/factory_test.go +++ b/pkg/scheduler/factory_test.go @@ -42,9 +42,8 @@ import ( apitesting "k8s.io/kubernetes/pkg/api/testing" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest" - "k8s.io/kubernetes/pkg/scheduler/apis/config" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" extenderv1 "k8s.io/kubernetes/pkg/scheduler/apis/extender/v1" frameworkplugins "k8s.io/kubernetes/pkg/scheduler/framework/plugins" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodelabel" @@ -101,7 +100,7 @@ func TestCreateFromConfig(t *testing.T) { {"name" : "PriorityOne", "weight" : 2}, {"name" : "PriorityTwo", "weight" : 1} ] }`) - if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil { + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), configData, &policy); err != nil { t.Errorf("Invalid configuration: %v", err) } @@ -139,13 +138,13 @@ func pluginExists(name, extensionPoint string, schedConf *Config) bool { return false } -func findPluginConfig(name string, schedConf *Config) config.PluginConfig { +func findPluginConfig(name string, schedConf *Config) schedulerapi.PluginConfig { for _, c := range schedConf.PluginConfig { if c.Name == name { return c } } - return config.PluginConfig{} + return schedulerapi.PluginConfig{} } func TestCreateFromConfigWithHardPodAffinitySymmetricWeight(t *testing.T) { @@ -179,7 +178,7 @@ func TestCreateFromConfigWithHardPodAffinitySymmetricWeight(t *testing.T) { ], "hardPodAffinitySymmetricWeight" : 10 }`) - if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil { + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), configData, &policy); err != nil { t.Errorf("Invalid configuration: %v", err) } factory.CreateFromConfig(policy) @@ -199,7 +198,7 @@ func TestCreateFromEmptyConfig(t *testing.T) { factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight, stopCh) configData = []byte(`{}`) - if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil { + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), configData, &policy); err != nil { t.Errorf("Invalid configuration: %v", err) } @@ -225,7 +224,7 @@ func TestCreateFromConfigWithUnspecifiedPredicatesOrPriorities(t *testing.T) { "apiVersion" : "v1" }`) var policy schedulerapi.Policy - if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil { + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), configData, &policy); err != nil { t.Fatalf("Invalid configuration: %v", err) } @@ -262,7 +261,7 @@ func TestCreateFromConfigWithEmptyPredicatesOrPriorities(t *testing.T) { "priorities" : [] }`) var policy schedulerapi.Policy - if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil { + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), configData, &policy); err != nil { t.Fatalf("Invalid configuration: %v", err) } @@ -543,7 +542,7 @@ func newConfigFactoryWithFrameworkRegistry( StopCh: stopCh, Registry: registry, Plugins: nil, - PluginConfig: []config.PluginConfig{}, + PluginConfig: []schedulerapi.PluginConfig{}, PluginConfigProducerRegistry: pluginConfigProducerRegistry, }) } @@ -719,34 +718,34 @@ func TestCreateWithFrameworkPlugins(t *testing.T) { PriorityToConfigProducer: make(map[string]frameworkplugins.ConfigProducer), } configProducerRegistry.RegisterPredicate(predicateOneName, - func(_ frameworkplugins.ConfigProducerArgs) (config.Plugins, []config.PluginConfig) { - return config.Plugins{ - Filter: &config.PluginSet{ - Enabled: []config.Plugin{ + func(_ frameworkplugins.ConfigProducerArgs) (schedulerapi.Plugins, []schedulerapi.PluginConfig) { + return schedulerapi.Plugins{ + Filter: &schedulerapi.PluginSet{ + Enabled: []schedulerapi.Plugin{ {Name: filterOneName}}}}, nil }) configProducerRegistry.RegisterPredicate(predicateTwoName, - func(_ frameworkplugins.ConfigProducerArgs) (config.Plugins, []config.PluginConfig) { - return config.Plugins{ - Filter: &config.PluginSet{ - Enabled: []config.Plugin{ + func(_ frameworkplugins.ConfigProducerArgs) (schedulerapi.Plugins, []schedulerapi.PluginConfig) { + return schedulerapi.Plugins{ + Filter: &schedulerapi.PluginSet{ + Enabled: []schedulerapi.Plugin{ {Name: filterTwoName}}}}, nil }) configProducerRegistry.RegisterPriority(priorityOneName, - func(args frameworkplugins.ConfigProducerArgs) (config.Plugins, []config.PluginConfig) { - return config.Plugins{ - Score: &config.PluginSet{ - Enabled: []config.Plugin{ + func(args frameworkplugins.ConfigProducerArgs) (schedulerapi.Plugins, []schedulerapi.PluginConfig) { + return schedulerapi.Plugins{ + Score: &schedulerapi.PluginSet{ + Enabled: []schedulerapi.Plugin{ {Name: scoreOneName, Weight: args.Weight}}}}, nil }) configProducerRegistry.RegisterPriority(priorityTwoName, - func(args frameworkplugins.ConfigProducerArgs) (config.Plugins, []config.PluginConfig) { - return config.Plugins{ - Score: &config.PluginSet{ - Enabled: []config.Plugin{ + func(args frameworkplugins.ConfigProducerArgs) (schedulerapi.Plugins, []schedulerapi.PluginConfig) { + return schedulerapi.Plugins{ + Score: &schedulerapi.PluginSet{ + Enabled: []schedulerapi.Plugin{ {Name: scoreTwoName, Weight: args.Weight}}}}, nil }) @@ -791,7 +790,7 @@ func TestCreateWithFrameworkPlugins(t *testing.T) { {"name" : "PriorityTwo", "weight" : 1}, {"name" : "PriorityThree", "weight" : 1} ] }`) - if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil { + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), configData, &policy); err != nil { t.Errorf("Invalid configuration: %v", err) } @@ -822,32 +821,32 @@ func TestCreateWithFrameworkPlugins(t *testing.T) { } // Verify the aggregated configuration. - wantPlugins := config.Plugins{ - QueueSort: &config.PluginSet{}, - PreFilter: &config.PluginSet{}, - Filter: &config.PluginSet{ - Enabled: []config.Plugin{ + wantPlugins := schedulerapi.Plugins{ + QueueSort: &schedulerapi.PluginSet{}, + PreFilter: &schedulerapi.PluginSet{}, + Filter: &schedulerapi.PluginSet{ + Enabled: []schedulerapi.Plugin{ {Name: filterOneName}, {Name: filterTwoName}, }, }, - PostFilter: &config.PluginSet{}, - Score: &config.PluginSet{ - Enabled: []config.Plugin{ + PostFilter: &schedulerapi.PluginSet{}, + Score: &schedulerapi.PluginSet{ + Enabled: []schedulerapi.Plugin{ {Name: scoreOneName, Weight: 2}, {Name: scoreTwoName, Weight: 1}, }, }, - Reserve: &config.PluginSet{}, - Permit: &config.PluginSet{}, - PreBind: &config.PluginSet{}, - Bind: &config.PluginSet{}, - PostBind: &config.PluginSet{}, - Unreserve: &config.PluginSet{}, + Reserve: &schedulerapi.PluginSet{}, + Permit: &schedulerapi.PluginSet{}, + PreBind: &schedulerapi.PluginSet{}, + Bind: &schedulerapi.PluginSet{}, + PostBind: &schedulerapi.PluginSet{}, + Unreserve: &schedulerapi.PluginSet{}, } - trans := cmp.Transformer("Sort", func(in []config.Plugin) []config.Plugin { - out := append([]config.Plugin(nil), in...) // Copy input to avoid mutating it + trans := cmp.Transformer("Sort", func(in []schedulerapi.Plugin) []schedulerapi.Plugin { + out := append([]schedulerapi.Plugin(nil), in...) // Copy input to avoid mutating it sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name }) return out }) diff --git a/pkg/scheduler/framework/v1alpha1/interface.go b/pkg/scheduler/framework/v1alpha1/interface.go index b0c0834a705..1bad76fcbe5 100644 --- a/pkg/scheduler/framework/v1alpha1/interface.go +++ b/pkg/scheduler/framework/v1alpha1/interface.go @@ -91,9 +91,6 @@ const ( // MaxTotalScore is the maximum total score. MaxTotalScore int64 = math.MaxInt64 - - // MaxWeight defines the max weight value. - MaxWeight int64 = MaxTotalScore / MaxNodeScore ) // Status indicates the result of running a plugin. It consists of a code and a diff --git a/pkg/scheduler/scheduler.go b/pkg/scheduler/scheduler.go index cf92a9a68a4..d3f723181c7 100644 --- a/pkg/scheduler/scheduler.go +++ b/pkg/scheduler/scheduler.go @@ -39,9 +39,8 @@ import ( "k8s.io/client-go/tools/events" podutil "k8s.io/kubernetes/pkg/api/v1/pod" kubefeatures "k8s.io/kubernetes/pkg/features" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest" - kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" "k8s.io/kubernetes/pkg/scheduler/core" frameworkplugins "k8s.io/kubernetes/pkg/scheduler/framework/plugins" framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" @@ -140,8 +139,8 @@ type schedulerOptions struct { // This registry contains out of tree plugins to be merged with default registry. frameworkOutOfTreeRegistry framework.Registry frameworkConfigProducerRegistry *frameworkplugins.ConfigProducerRegistry - frameworkPlugins *kubeschedulerconfig.Plugins - frameworkPluginConfig []kubeschedulerconfig.PluginConfig + frameworkPlugins *schedulerapi.Plugins + frameworkPluginConfig []schedulerapi.PluginConfig } // Option configures a Scheduler @@ -205,14 +204,14 @@ func WithFrameworkConfigProducerRegistry(registry *frameworkplugins.ConfigProduc } // WithFrameworkPlugins sets the plugins that the framework should be configured with. -func WithFrameworkPlugins(plugins *kubeschedulerconfig.Plugins) Option { +func WithFrameworkPlugins(plugins *schedulerapi.Plugins) Option { return func(o *schedulerOptions) { o.frameworkPlugins = plugins } } // WithFrameworkPluginConfig sets the PluginConfig slice that the framework should be configured with. -func WithFrameworkPluginConfig(pluginConfig []kubeschedulerconfig.PluginConfig) Option { +func WithFrameworkPluginConfig(pluginConfig []schedulerapi.PluginConfig) Option { return func(o *schedulerOptions) { o.frameworkPluginConfig = pluginConfig } @@ -257,7 +256,7 @@ func New(client clientset.Interface, informerFactory informers.SharedInformerFactory, podInformer coreinformers.PodInformer, recorder events.EventRecorder, - schedulerAlgorithmSource kubeschedulerconfig.SchedulerAlgorithmSource, + schedulerAlgorithmSource schedulerapi.SchedulerAlgorithmSource, stopCh <-chan struct{}, opts ...Option) (*Scheduler, error) { @@ -379,7 +378,7 @@ func initPolicyFromFile(policyFile string, policy *schedulerapi.Policy) error { if err != nil { return fmt.Errorf("couldn't read policy config: %v", err) } - err = runtime.DecodeInto(latestschedulerapi.Codec, []byte(data), policy) + err = runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), []byte(data), policy) if err != nil { return fmt.Errorf("invalid policy: %v", err) } @@ -387,17 +386,17 @@ func initPolicyFromFile(policyFile string, policy *schedulerapi.Policy) error { } // initPolicyFromConfigMap initialize policy from configMap -func initPolicyFromConfigMap(client clientset.Interface, policyRef *kubeschedulerconfig.SchedulerPolicyConfigMapSource, policy *schedulerapi.Policy) error { +func initPolicyFromConfigMap(client clientset.Interface, policyRef *schedulerapi.SchedulerPolicyConfigMapSource, policy *schedulerapi.Policy) error { // Use a policy serialized in a config map value. policyConfigMap, err := client.CoreV1().ConfigMaps(policyRef.Namespace).Get(policyRef.Name, metav1.GetOptions{}) if err != nil { return fmt.Errorf("couldn't get policy config map %s/%s: %v", policyRef.Namespace, policyRef.Name, err) } - data, found := policyConfigMap.Data[kubeschedulerconfig.SchedulerPolicyConfigMapKey] + data, found := policyConfigMap.Data[schedulerapi.SchedulerPolicyConfigMapKey] if !found { - return fmt.Errorf("missing policy config map value at key %q", kubeschedulerconfig.SchedulerPolicyConfigMapKey) + return fmt.Errorf("missing policy config map value at key %q", schedulerapi.SchedulerPolicyConfigMapKey) } - err = runtime.DecodeInto(latestschedulerapi.Codec, []byte(data), policy) + err = runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), []byte(data), policy) if err != nil { return fmt.Errorf("invalid policy: %v", err) } diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go index 8e85eb4749b..f511b373567 100644 --- a/pkg/scheduler/scheduler_test.go +++ b/pkg/scheduler/scheduler_test.go @@ -46,8 +46,8 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/core" framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" internalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" diff --git a/pkg/scheduler/api/doc.go b/staging/src/k8s.io/kube-scheduler/config/v1/doc.go similarity index 83% rename from pkg/scheduler/api/doc.go rename to staging/src/k8s.io/kube-scheduler/config/v1/doc.go index c768a8c92cf..a94d3193909 100644 --- a/pkg/scheduler/api/doc.go +++ b/staging/src/k8s.io/kube-scheduler/config/v1/doc.go @@ -15,6 +15,7 @@ limitations under the License. */ // +k8s:deepcopy-gen=package +// +k8s:openapi-gen=true +// +groupName=kubescheduler.config.k8s.io -// Package api contains scheduler API objects. -package api // import "k8s.io/kubernetes/pkg/scheduler/api" +package v1 // import "k8s.io/kube-scheduler/config/v1" diff --git a/pkg/scheduler/api/register.go b/staging/src/k8s.io/kube-scheduler/config/v1/register.go similarity index 56% rename from pkg/scheduler/api/register.go rename to staging/src/k8s.io/kube-scheduler/config/v1/register.go index 4852cd559e5..d5fcf8315a3 100644 --- a/pkg/scheduler/api/register.go +++ b/staging/src/k8s.io/kube-scheduler/config/v1/register.go @@ -14,42 +14,32 @@ See the License for the specific language governing permissions and limitations under the License. */ -package api +package v1 import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) -// Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered. -// TODO: remove this, scheduler should not have its own scheme. -var Scheme = runtime.NewScheme() +// GroupName is the group name used in this package +const GroupName = "kubescheduler.config.k8s.io" // SchemeGroupVersion is group version used to register these objects -// TODO this should be in the "scheduler" group -var SchemeGroupVersion = schema.GroupVersion{Group: "", Version: runtime.APIVersionInternal} +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} var ( - // SchemeBuilder defines a SchemeBuilder object. + // SchemeBuilder is the scheme builder with scheme init functions to run for this API package SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) - // AddToScheme is used to add stored functions to scheme. + // AddToScheme is a global function that registers this API group & version to a scheme AddToScheme = SchemeBuilder.AddToScheme ) -func init() { - if err := addKnownTypes(Scheme); err != nil { - // Programmer error. - panic(err) - } -} - +// addKnownTypes registers known types to the given scheme func addKnownTypes(scheme *runtime.Scheme) error { - if err := scheme.AddIgnoredConversionType(&metav1.TypeMeta{}, &metav1.TypeMeta{}); err != nil { - return err - } scheme.AddKnownTypes(SchemeGroupVersion, &Policy{}, ) + // also register into the v1 group for API backward compatibility + scheme.AddKnownTypes(schema.GroupVersion{Group: "", Version: "v1"}, &Policy{}) return nil } diff --git a/pkg/scheduler/api/v1/types.go b/staging/src/k8s.io/kube-scheduler/config/v1/types.go similarity index 94% rename from pkg/scheduler/api/v1/types.go rename to staging/src/k8s.io/kube-scheduler/config/v1/types.go index dce662ea434..a7dbdbb97f7 100644 --- a/pkg/scheduler/api/v1/types.go +++ b/staging/src/k8s.io/kube-scheduler/config/v1/types.go @@ -20,7 +20,6 @@ import ( gojson "encoding/json" "time" - apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -34,7 +33,7 @@ type Policy struct { // Holds the information to configure the priority functions Priorities []PriorityPolicy `json:"priorities"` // Holds the information to communicate with the extender(s) - ExtenderConfigs []ExtenderConfig `json:"extenders"` + Extenders []Extender `json:"extenders"` // RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule // corresponding to every RequiredDuringScheduling affinity rule. // HardPodAffinitySymmetricWeight represents the weight of implicit PreferredDuringScheduling affinity rule, in the range 1-100. @@ -129,8 +128,8 @@ type LabelPreference struct { // RequestedToCapacityRatioArguments holds arguments specific to RequestedToCapacityRatio priority function. type RequestedToCapacityRatioArguments struct { // Array of point defining priority function shape. - UtilizationShape []UtilizationShapePoint `json:"shape"` - Resources []ResourceSpec `json:"resources,omitempty"` + Shape []UtilizationShapePoint `json:"shape"` + Resources []ResourceSpec `json:"resources,omitempty"` } // UtilizationShapePoint represents single point of priority function shape. @@ -144,7 +143,7 @@ type UtilizationShapePoint struct { // 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 apiv1.ResourceName `json:"name"` + Name string `json:"name"` // Weight of the resource. Weight int64 `json:"weight,omitempty"` } @@ -153,7 +152,7 @@ type ResourceSpec struct { // managed by an extender. type ExtenderManagedResource struct { // Name is the extended resource name. - Name apiv1.ResourceName `json:"name"` + Name string `json:"name"` // IgnoredByScheduler indicates whether kube-scheduler should ignore this // resource when applying predicates. IgnoredByScheduler bool `json:"ignoredByScheduler,omitempty"` @@ -186,9 +185,9 @@ type ExtenderTLSConfig struct { CAData []byte `json:"caData,omitempty"` } -// ExtenderConfig holds the parameters used to communicate with the extender. If a verb is unspecified/empty, +// 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 ExtenderConfig struct { +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. @@ -230,14 +229,14 @@ type ExtenderConfig struct { Ignorable bool `json:"ignorable,omitempty"` } -// caseInsensitiveExtenderConfig is a type alias which lets us use the stdlib case-insensitive decoding +// caseInsensitiveExtender is a type alias which lets us use the stdlib case-insensitive decoding // to preserve compatibility with incorrectly specified scheduler config fields: // * BindVerb, which originally did not specify a json tag, and required upper-case serialization in 1.7 // * TLSConfig, which uses a struct not intended for serialization, and does not include any json tags -type caseInsensitiveExtenderConfig *ExtenderConfig +type caseInsensitiveExtender *Extender // UnmarshalJSON implements the json.Unmarshaller interface. // This preserves compatibility with incorrect case-insensitive configuration fields. -func (t *ExtenderConfig) UnmarshalJSON(b []byte) error { - return gojson.Unmarshal(b, caseInsensitiveExtenderConfig(t)) +func (t *Extender) UnmarshalJSON(b []byte) error { + return gojson.Unmarshal(b, caseInsensitiveExtender(t)) } diff --git a/test/integration/scheduler/extender_test.go b/test/integration/scheduler/extender_test.go index f1135c0d344..b42dceb660a 100644 --- a/test/integration/scheduler/extender_test.go +++ b/test/integration/scheduler/extender_test.go @@ -33,7 +33,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" extenderv1 "k8s.io/kubernetes/pkg/scheduler/apis/extender/v1" imageutils "k8s.io/kubernetes/test/utils/image" ) @@ -315,7 +315,7 @@ func TestSchedulerExtender(t *testing.T) { defer es3.Close() policy := schedulerapi.Policy{ - ExtenderConfigs: []schedulerapi.ExtenderConfig{ + Extenders: []schedulerapi.Extender{ { URLPrefix: es1.URL, FilterVerb: filter, diff --git a/test/integration/scheduler/util.go b/test/integration/scheduler/util.go index 2ad9f304123..28b8fe46af5 100644 --- a/test/integration/scheduler/util.go +++ b/test/integration/scheduler/util.go @@ -50,12 +50,12 @@ import ( podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/controller/disruption" "k8s.io/kubernetes/pkg/scheduler" - latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest" - schedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config" + "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme" + schedulerapiv1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1" // Register defaults in pkg/scheduler/algorithmprovider. _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" taintutils "k8s.io/kubernetes/pkg/util/taints" "k8s.io/kubernetes/test/integration/framework" imageutils "k8s.io/kubernetes/test/utils/image" @@ -72,19 +72,25 @@ type testContext struct { cancelFn context.CancelFunc } -func createAlgorithmSourceFromPolicy(policy *schedulerapi.Policy, clientSet clientset.Interface) schedulerconfig.SchedulerAlgorithmSource { - policyString := runtime.EncodeOrDie(latestschedulerapi.Codec, policy) +func createAlgorithmSourceFromPolicy(policy *schedulerapi.Policy, clientSet clientset.Interface) schedulerapi.SchedulerAlgorithmSource { + // Serialize the Policy object into a ConfigMap later. + info, ok := runtime.SerializerInfoForMediaType(scheme.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON) + if !ok { + panic("could not find json serializer") + } + encoder := scheme.Codecs.EncoderForVersion(info.Serializer, schedulerapiv1.SchemeGroupVersion) + policyString := runtime.EncodeOrDie(encoder, policy) configPolicyName := "scheduler-custom-policy-config" policyConfigMap := v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: configPolicyName}, - Data: map[string]string{schedulerconfig.SchedulerPolicyConfigMapKey: policyString}, + Data: map[string]string{schedulerapi.SchedulerPolicyConfigMapKey: policyString}, } policyConfigMap.APIVersion = "v1" clientSet.CoreV1().ConfigMaps(metav1.NamespaceSystem).Create(&policyConfigMap) - return schedulerconfig.SchedulerAlgorithmSource{ - Policy: &schedulerconfig.SchedulerPolicySource{ - ConfigMap: &schedulerconfig.SchedulerPolicyConfigMapSource{ + return schedulerapi.SchedulerAlgorithmSource{ + Policy: &schedulerapi.SchedulerPolicySource{ + ConfigMap: &schedulerapi.SchedulerPolicyConfigMapSource{ Namespace: policyConfigMap.Namespace, Name: policyConfigMap.Name, }, @@ -175,12 +181,12 @@ func initTestSchedulerWithOptions( legacyscheme.Scheme, v1.DefaultSchedulerName, ) - var algorithmSrc schedulerconfig.SchedulerAlgorithmSource + var algorithmSrc schedulerapi.SchedulerAlgorithmSource if policy != nil { algorithmSrc = createAlgorithmSourceFromPolicy(policy, context.clientSet) } else { - provider := schedulerconfig.SchedulerDefaultProviderName - algorithmSrc = schedulerconfig.SchedulerAlgorithmSource{ + provider := schedulerapi.SchedulerDefaultProviderName + algorithmSrc = schedulerapi.SchedulerAlgorithmSource{ Provider: &provider, } }