Skip to content

Commit 3e5f6bd

Browse files
authored
Merge pull request kubernetes#84129 from obitech/lenient_path_strict_decoding_kube_scheduler
Add lenient decoding path for v1alpha1 kube-scheduler config
2 parents 1488460 + b15aba5 commit 3e5f6bd

File tree

7 files changed

+159
-7
lines changed

7 files changed

+159
-7
lines changed

cmd/kube-scheduler/app/options/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ go_library(
3636
"//staging/src/k8s.io/client-go/tools/leaderelection/resourcelock:go_default_library",
3737
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
3838
"//staging/src/k8s.io/component-base/cli/flag:go_default_library",
39+
"//staging/src/k8s.io/component-base/codec:go_default_library",
3940
"//staging/src/k8s.io/component-base/config:go_default_library",
4041
"//staging/src/k8s.io/kube-scheduler/config/v1alpha1:go_default_library",
4142
"//vendor/github.com/spf13/pflag:go_default_library",

cmd/kube-scheduler/app/options/configfile.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ import (
2121
"io/ioutil"
2222
"os"
2323

24+
"k8s.io/klog"
25+
2426
"k8s.io/apimachinery/pkg/runtime"
27+
"k8s.io/component-base/codec"
2528
kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
2629
kubeschedulerscheme "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme"
2730
kubeschedulerconfigv1alpha1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1alpha1"
@@ -38,8 +41,28 @@ func loadConfigFromFile(file string) (*kubeschedulerconfig.KubeSchedulerConfigur
3841

3942
func loadConfig(data []byte) (*kubeschedulerconfig.KubeSchedulerConfiguration, error) {
4043
configObj := &kubeschedulerconfig.KubeSchedulerConfiguration{}
41-
if err := runtime.DecodeInto(kubeschedulerscheme.Codecs.UniversalDecoder(), data, configObj); err != nil {
42-
return nil, err
44+
// The UniversalDecoder runs defaulting and returns the internal type by default.
45+
err := runtime.DecodeInto(kubeschedulerscheme.Codecs.UniversalDecoder(), data, configObj)
46+
if err != nil {
47+
// Try strict decoding first. If that fails decode with a lenient
48+
// decoder, which has only v1alpha1 registered, and log a warning.
49+
// The lenient path is to be dropped when support for v1alpha1 is dropped.
50+
if !runtime.IsStrictDecodingError(err) {
51+
return nil, err
52+
}
53+
54+
var lenientErr error
55+
_, lenientCodecs, lenientErr := codec.NewLenientSchemeAndCodecs(
56+
kubeschedulerconfig.AddToScheme,
57+
kubeschedulerconfigv1alpha1.AddToScheme,
58+
)
59+
if lenientErr != nil {
60+
return nil, lenientErr
61+
}
62+
if lenientErr = runtime.DecodeInto(lenientCodecs.UniversalDecoder(), data, configObj); lenientErr != nil {
63+
return nil, fmt.Errorf("failed lenient decoding: %v", err)
64+
}
65+
klog.Warningf("using lenient decoding as strict decoding failed: %v", err)
4366
}
4467

4568
return configObj, nil

cmd/kube-scheduler/app/options/options_test.go

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -472,16 +472,76 @@ pluginConfig:
472472
options: &Options{
473473
ConfigFile: unknownFieldConfig,
474474
},
475-
expectedError: "found unknown field: foo",
476-
checkErrFn: runtime.IsStrictDecodingError,
475+
// TODO (obitech): Remove this comment and add a new test for v1alpha2, when it's available, as this should fail then.
476+
// expectedError: "found unknown field: foo",
477+
// checkErrFn: runtime.IsStrictDecodingError,
478+
expectedUsername: "config",
479+
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
480+
SchedulerName: "default-scheduler",
481+
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
482+
HardPodAffinitySymmetricWeight: 1,
483+
HealthzBindAddress: "0.0.0.0:10251",
484+
MetricsBindAddress: "0.0.0.0:10251",
485+
LeaderElection: kubeschedulerconfig.KubeSchedulerLeaderElectionConfiguration{
486+
LeaderElectionConfiguration: componentbaseconfig.LeaderElectionConfiguration{
487+
LeaderElect: true,
488+
LeaseDuration: metav1.Duration{Duration: 15 * time.Second},
489+
RenewDeadline: metav1.Duration{Duration: 10 * time.Second},
490+
RetryPeriod: metav1.Duration{Duration: 2 * time.Second},
491+
ResourceLock: "endpointsleases",
492+
ResourceNamespace: "kube-system",
493+
ResourceName: "kube-scheduler",
494+
},
495+
},
496+
ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
497+
Kubeconfig: configKubeconfig,
498+
QPS: 50,
499+
Burst: 100,
500+
ContentType: "application/vnd.kubernetes.protobuf",
501+
},
502+
BindTimeoutSeconds: &defaultBindTimeoutSeconds,
503+
PodInitialBackoffSeconds: &defaultPodInitialBackoffSeconds,
504+
PodMaxBackoffSeconds: &defaultPodMaxBackoffSeconds,
505+
Plugins: nil,
506+
},
477507
},
478508
{
479509
name: "duplicate fields",
480510
options: &Options{
481511
ConfigFile: duplicateFieldConfig,
482512
},
483-
expectedError: `key "leaderElect" already set`,
484-
checkErrFn: runtime.IsStrictDecodingError,
513+
// TODO (obitech): Remove this comment and add a new test for v1alpha2, when it's available, as this should fail then.
514+
// expectedError: `key "leaderElect" already set`,
515+
// checkErrFn: runtime.IsStrictDecodingError,
516+
expectedUsername: "config",
517+
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
518+
SchedulerName: "default-scheduler",
519+
AlgorithmSource: kubeschedulerconfig.SchedulerAlgorithmSource{Provider: &defaultSource},
520+
HardPodAffinitySymmetricWeight: 1,
521+
HealthzBindAddress: "0.0.0.0:10251",
522+
MetricsBindAddress: "0.0.0.0:10251",
523+
LeaderElection: kubeschedulerconfig.KubeSchedulerLeaderElectionConfiguration{
524+
LeaderElectionConfiguration: componentbaseconfig.LeaderElectionConfiguration{
525+
LeaderElect: false,
526+
LeaseDuration: metav1.Duration{Duration: 15 * time.Second},
527+
RenewDeadline: metav1.Duration{Duration: 10 * time.Second},
528+
RetryPeriod: metav1.Duration{Duration: 2 * time.Second},
529+
ResourceLock: "endpointsleases",
530+
ResourceNamespace: "kube-system",
531+
ResourceName: "kube-scheduler",
532+
},
533+
},
534+
ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
535+
Kubeconfig: configKubeconfig,
536+
QPS: 50,
537+
Burst: 100,
538+
ContentType: "application/vnd.kubernetes.protobuf",
539+
},
540+
BindTimeoutSeconds: &defaultBindTimeoutSeconds,
541+
PodInitialBackoffSeconds: &defaultPodInitialBackoffSeconds,
542+
PodMaxBackoffSeconds: &defaultPodMaxBackoffSeconds,
543+
Plugins: nil,
544+
},
485545
},
486546
}
487547

@@ -523,7 +583,7 @@ pluginConfig:
523583
return
524584
}
525585
if username != tc.expectedUsername {
526-
t.Errorf("expected server call with user %s, got %s", tc.expectedUsername, username)
586+
t.Errorf("expected server call with user %q, got %q", tc.expectedUsername, username)
527587
}
528588
})
529589
}

staging/src/k8s.io/component-base/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ filegroup(
1111
":package-srcs",
1212
"//staging/src/k8s.io/component-base/cli/flag:all-srcs",
1313
"//staging/src/k8s.io/component-base/cli/globalflag:all-srcs",
14+
"//staging/src/k8s.io/component-base/codec:all-srcs",
1415
"//staging/src/k8s.io/component-base/config:all-srcs",
1516
"//staging/src/k8s.io/component-base/featuregate:all-srcs",
1617
"//staging/src/k8s.io/component-base/logs:all-srcs",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
load("@io_bazel_rules_go//go:def.bzl", "go_library")
2+
3+
go_library(
4+
name = "go_default_library",
5+
srcs = ["codec.go"],
6+
importmap = "k8s.io/kubernetes/vendor/k8s.io/component-base/codec",
7+
importpath = "k8s.io/component-base/codec",
8+
visibility = ["//visibility:public"],
9+
deps = [
10+
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
11+
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
12+
],
13+
)
14+
15+
filegroup(
16+
name = "package-srcs",
17+
srcs = glob(["**"]),
18+
tags = ["automanaged"],
19+
visibility = ["//visibility:private"],
20+
)
21+
22+
filegroup(
23+
name = "all-srcs",
24+
srcs = [":package-srcs"],
25+
tags = ["automanaged"],
26+
visibility = ["//visibility:public"],
27+
)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package codec
18+
19+
import (
20+
"fmt"
21+
22+
"k8s.io/apimachinery/pkg/runtime"
23+
"k8s.io/apimachinery/pkg/runtime/serializer"
24+
)
25+
26+
// NewLenientSchemeAndCodecs constructs a CodecFactory with strict decoding
27+
// disabled, that has only the Schemes registered into it which are passed
28+
// and added via AddToScheme functions. This can be used to skip strict decoding
29+
// a specific version only.
30+
func NewLenientSchemeAndCodecs(addToSchemeFns ...func(s *runtime.Scheme) error) (*runtime.Scheme, *serializer.CodecFactory, error) {
31+
lenientScheme := runtime.NewScheme()
32+
for _, s := range addToSchemeFns {
33+
if err := s(lenientScheme); err != nil {
34+
return nil, nil, fmt.Errorf("unable to add API to lenient scheme: %v", err)
35+
}
36+
}
37+
lenientCodecs := serializer.NewCodecFactory(lenientScheme, serializer.DisableStrict)
38+
return lenientScheme, &lenientCodecs, nil
39+
}

vendor/modules.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,6 +1650,7 @@ k8s.io/code-generator/third_party/forked/golang/reflect
16501650
# k8s.io/component-base v0.0.0 => ./staging/src/k8s.io/component-base
16511651
k8s.io/component-base/cli/flag
16521652
k8s.io/component-base/cli/globalflag
1653+
k8s.io/component-base/codec
16531654
k8s.io/component-base/config
16541655
k8s.io/component-base/config/v1alpha1
16551656
k8s.io/component-base/config/validation

0 commit comments

Comments
 (0)