diff --git a/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go b/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go index 06e793a518..903b08b883 100644 --- a/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go +++ b/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go @@ -349,7 +349,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {"name": "TaintTolerationPriority", "weight": 2}, {"name": "InterPodAffinityPriority", "weight": 2}, {"name": "MostRequestedPriority", "weight": 2} - ] + ],"extenders": [{ + "urlPrefix": "/prefix", + "filterVerb": "filter", + "prioritizeVerb": "prioritize", + "weight": 1, + "BindVerb": "bind", + "enableHttps": true, + "tlsConfig": {"Insecure":true}, + "httpTimeout": 1, + "nodeCacheCapable": true + }] }`, ExpectedPolicy: schedulerapi.Policy{ Predicates: []schedulerapi.PredicatePolicy{ @@ -382,6 +392,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "InterPodAffinityPriority", Weight: 2}, {Name: "MostRequestedPriority", Weight: 2}, }, + ExtenderConfigs: []schedulerapi.ExtenderConfig{{ + 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: &restclient.TLSClientConfig{Insecure: true}, + HTTPTimeout: 1, + NodeCacheCapable: true, + }}, }, }, // Do not change this JSON after the corresponding release has been tagged. @@ -419,7 +440,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {"name": "TaintTolerationPriority", "weight": 2}, {"name": "InterPodAffinityPriority", "weight": 2}, {"name": "MostRequestedPriority", "weight": 2} - ] + ],"extenders": [{ + "urlPrefix": "/prefix", + "filterVerb": "filter", + "prioritizeVerb": "prioritize", + "weight": 1, + "bindVerb": "bind", + "enableHttps": true, + "tlsConfig": {"Insecure":true}, + "httpTimeout": 1, + "nodeCacheCapable": true + }] }`, ExpectedPolicy: schedulerapi.Policy{ Predicates: []schedulerapi.PredicatePolicy{ @@ -453,6 +484,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "InterPodAffinityPriority", Weight: 2}, {Name: "MostRequestedPriority", Weight: 2}, }, + ExtenderConfigs: []schedulerapi.ExtenderConfig{{ + URLPrefix: "/prefix", + FilterVerb: "filter", + PrioritizeVerb: "prioritize", + Weight: 1, + BindVerb: "bind", // 1.8 became case-insensitive and tolerated "bindVerb" + EnableHTTPS: true, + TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + HTTPTimeout: 1, + NodeCacheCapable: true, + }}, }, }, // Do not change this JSON after the corresponding release has been tagged. @@ -491,7 +533,17 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {"name": "TaintTolerationPriority", "weight": 2}, {"name": "InterPodAffinityPriority", "weight": 2}, {"name": "MostRequestedPriority", "weight": 2} - ] + ],"extenders": [{ + "urlPrefix": "/prefix", + "filterVerb": "filter", + "prioritizeVerb": "prioritize", + "weight": 1, + "bindVerb": "bind", + "enableHttps": true, + "tlsConfig": {"Insecure":true}, + "httpTimeout": 1, + "nodeCacheCapable": true + }] }`, ExpectedPolicy: schedulerapi.Policy{ Predicates: []schedulerapi.PredicatePolicy{ @@ -526,8 +578,20 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "InterPodAffinityPriority", Weight: 2}, {Name: "MostRequestedPriority", Weight: 2}, }, + ExtenderConfigs: []schedulerapi.ExtenderConfig{{ + URLPrefix: "/prefix", + FilterVerb: "filter", + PrioritizeVerb: "prioritize", + Weight: 1, + BindVerb: "bind", // 1.9 was case-insensitive and tolerated "bindVerb" + EnableHTTPS: true, + TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + HTTPTimeout: 1, + NodeCacheCapable: true, + }}, }, }, + // Do not change this JSON after the corresponding release has been tagged. // A failure indicates backwards compatibility with the specified release was broken. "1.10": { @@ -565,7 +629,19 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {"name": "TaintTolerationPriority", "weight": 2}, {"name": "InterPodAffinityPriority", "weight": 2}, {"name": "MostRequestedPriority", "weight": 2} - ] + ],"extenders": [{ + "urlPrefix": "/prefix", + "filterVerb": "filter", + "prioritizeVerb": "prioritize", + "weight": 1, + "bindVerb": "bind", + "enableHttps": true, + "tlsConfig": {"Insecure":true}, + "httpTimeout": 1, + "nodeCacheCapable": true, + "managedResources": [{"name":"example.com/foo","ignoredByScheduler":true}], + "ignorable":true + }] }`, ExpectedPolicy: schedulerapi.Policy{ Predicates: []schedulerapi.PredicatePolicy{ @@ -601,6 +677,19 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { {Name: "InterPodAffinityPriority", Weight: 2}, {Name: "MostRequestedPriority", Weight: 2}, }, + ExtenderConfigs: []schedulerapi.ExtenderConfig{{ + URLPrefix: "/prefix", + FilterVerb: "filter", + PrioritizeVerb: "prioritize", + Weight: 1, + BindVerb: "bind", // 1.10 was case-insensitive and tolerated "bindVerb" + EnableHTTPS: true, + TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + HTTPTimeout: 1, + NodeCacheCapable: true, + ManagedResources: []schedulerapi.ExtenderManagedResource{{Name: v1.ResourceName("example.com/foo"), IgnoredByScheduler: true}}, + Ignorable: true, + }}, }, }, // Do not change this JSON after the corresponding release has been tagged. @@ -651,7 +740,19 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { ] } }} - ] + ],"extenders": [{ + "urlPrefix": "/prefix", + "filterVerb": "filter", + "prioritizeVerb": "prioritize", + "weight": 1, + "bindVerb": "bind", + "enableHttps": true, + "tlsConfig": {"Insecure":true}, + "httpTimeout": 1, + "nodeCacheCapable": true, + "managedResources": [{"name":"example.com/foo","ignoredByScheduler":true}], + "ignorable":true + }] }`, ExpectedPolicy: schedulerapi.Policy{ Predicates: []schedulerapi.PredicatePolicy{ @@ -698,6 +799,19 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { }, }, }, + ExtenderConfigs: []schedulerapi.ExtenderConfig{{ + URLPrefix: "/prefix", + FilterVerb: "filter", + PrioritizeVerb: "prioritize", + Weight: 1, + BindVerb: "bind", // 1.11 restored case-sensitivity, but allowed either "BindVerb" or "bindVerb" + EnableHTTPS: true, + TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + HTTPTimeout: 1, + NodeCacheCapable: true, + ManagedResources: []schedulerapi.ExtenderManagedResource{{Name: v1.ResourceName("example.com/foo"), IgnoredByScheduler: true}}, + Ignorable: true, + }}, }, }, } diff --git a/pkg/scheduler/api/v1/types.go b/pkg/scheduler/api/v1/types.go index 4058d06889..10ea29bb32 100644 --- a/pkg/scheduler/api/v1/types.go +++ b/pkg/scheduler/api/v1/types.go @@ -17,6 +17,7 @@ limitations under the License. package v1 import ( + gojson "encoding/json" "time" apiv1 "k8s.io/api/core/v1" @@ -195,6 +196,18 @@ type ExtenderConfig struct { Ignorable bool `json:"ignorable,omitempty"` } +// caseInsensitiveExtenderConfig 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 + +// 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)) +} + // ExtenderArgs represents the arguments needed by the extender to filter/prioritize // nodes for a pod. type ExtenderArgs struct {