Commit 0af9f756 authored by Michael Taufen's avatar Michael Taufen

Don't register the kubeletconfig group with the default Scheme

parent 683f09c6
...@@ -12,11 +12,10 @@ go_library( ...@@ -12,11 +12,10 @@ go_library(
"options.go", "options.go",
], ],
deps = [ deps = [
"//pkg/api:go_default_library",
"//pkg/apis/componentconfig:go_default_library", "//pkg/apis/componentconfig:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/install:go_default_library", "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/validation:go_default_library", "//pkg/kubelet/apis/kubeletconfig/validation:go_default_library",
"//pkg/util/taints:go_default_library", "//pkg/util/taints:go_default_library",
......
...@@ -25,14 +25,12 @@ import ( ...@@ -25,14 +25,12 @@ import (
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/apiserver/pkg/util/flag" "k8s.io/apiserver/pkg/util/flag"
utilflag "k8s.io/apiserver/pkg/util/flag" utilflag "k8s.io/apiserver/pkg/util/flag"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/componentconfig" "k8s.io/kubernetes/pkg/apis/componentconfig"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
kubeletconfigvalidation "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation" kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
// Need to make sure the kubeletconfig api is installed so defaulting funcs work
_ "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/install"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
kubeletconfigvalidation "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation"
utiltaints "k8s.io/kubernetes/pkg/util/taints" utiltaints "k8s.io/kubernetes/pkg/util/taints"
"github.com/spf13/pflag" "github.com/spf13/pflag"
...@@ -142,10 +140,14 @@ func ValidateKubeletFlags(f *KubeletFlags) error { ...@@ -142,10 +140,14 @@ func ValidateKubeletFlags(f *KubeletFlags) error {
// NewKubeletConfiguration will create a new KubeletConfiguration with default values // NewKubeletConfiguration will create a new KubeletConfiguration with default values
func NewKubeletConfiguration() (*kubeletconfig.KubeletConfiguration, error) { func NewKubeletConfiguration() (*kubeletconfig.KubeletConfiguration, error) {
scheme, _, err := kubeletscheme.NewSchemeAndCodecs()
if err != nil {
return nil, err
}
versioned := &v1alpha1.KubeletConfiguration{} versioned := &v1alpha1.KubeletConfiguration{}
api.Scheme.Default(versioned) scheme.Default(versioned)
config := &kubeletconfig.KubeletConfiguration{} config := &kubeletconfig.KubeletConfiguration{}
if err := api.Scheme.Convert(versioned, config, nil); err != nil { if err := scheme.Convert(versioned, config, nil); err != nil {
return nil, err return nil, err
} }
return config, nil return config, nil
......
...@@ -756,7 +756,8 @@ func parseResourceList(m kubeletconfiginternal.ConfigurationMap) (v1.ResourceLis ...@@ -756,7 +756,8 @@ func parseResourceList(m kubeletconfiginternal.ConfigurationMap) (v1.ResourceLis
} }
// BootstrapKubeletConfigController constructs and bootstrap a configuration controller // BootstrapKubeletConfigController constructs and bootstrap a configuration controller
func BootstrapKubeletConfigController(flags *options.KubeletFlags, func BootstrapKubeletConfigController(
flags *options.KubeletFlags,
defaultConfig *kubeletconfiginternal.KubeletConfiguration) (*kubeletconfiginternal.KubeletConfiguration, *kubeletconfig.Controller, error) { defaultConfig *kubeletconfiginternal.KubeletConfiguration) (*kubeletconfiginternal.KubeletConfiguration, *kubeletconfig.Controller, error) {
var err error var err error
// Alpha Dynamic Configuration Implementation; this section only loads config from disk, it does not contact the API server // Alpha Dynamic Configuration Implementation; this section only loads config from disk, it does not contact the API server
...@@ -777,7 +778,10 @@ func BootstrapKubeletConfigController(flags *options.KubeletFlags, ...@@ -777,7 +778,10 @@ func BootstrapKubeletConfigController(flags *options.KubeletFlags,
} }
// get the latest KubeletConfiguration checkpoint from disk, or load the init or default config if no valid checkpoints exist // get the latest KubeletConfiguration checkpoint from disk, or load the init or default config if no valid checkpoints exist
kubeletConfigController := kubeletconfig.NewController(initConfigDir, dynamicConfigDir, defaultConfig) kubeletConfigController, err := kubeletconfig.NewController(initConfigDir, dynamicConfigDir, defaultConfig)
if err != nil {
return nil, nil, fmt.Errorf("failed to construct controller, error: %v", err)
}
kubeletConfig, err := kubeletConfigController.Bootstrap() kubeletConfig, err := kubeletConfigController.Bootstrap()
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to determine a valid configuration, error: %v", err) return nil, nil, fmt.Errorf("failed to determine a valid configuration, error: %v", err)
......
...@@ -89,7 +89,10 @@ func main() { ...@@ -89,7 +89,10 @@ func main() {
} }
// construct a KubeletServer from kubeletFlags and kubeletConfig // construct a KubeletServer from kubeletFlags and kubeletConfig
kubeletServer := &options.KubeletServer{KubeletFlags: *kubeletFlags, KubeletConfiguration: *kubeletConfig} kubeletServer := &options.KubeletServer{
KubeletFlags: *kubeletFlags,
KubeletConfiguration: *kubeletConfig,
}
// use kubeletServer to construct the default KubeletDeps // use kubeletServer to construct the default KubeletDeps
kubeletDeps, err := app.UnsecuredDependencies(kubeletServer) kubeletDeps, err := app.UnsecuredDependencies(kubeletServer)
......
...@@ -36,7 +36,7 @@ filegroup( ...@@ -36,7 +36,7 @@ filegroup(
name = "all-srcs", name = "all-srcs",
srcs = [ srcs = [
":package-srcs", ":package-srcs",
"//pkg/kubelet/apis/kubeletconfig/install:all-srcs", "//pkg/kubelet/apis/kubeletconfig/scheme:all-srcs",
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:all-srcs", "//pkg/kubelet/apis/kubeletconfig/v1alpha1:all-srcs",
"//pkg/kubelet/apis/kubeletconfig/validation:all-srcs", "//pkg/kubelet/apis/kubeletconfig/validation:all-srcs",
], ],
......
package(default_visibility = ["//visibility:public"]) load("@io_bazel_rules_go//go:def.bzl", "go_library")
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["install.go"], srcs = ["scheme.go"],
tags = ["automanaged"], visibility = ["//visibility:public"],
deps = [ deps = [
"//pkg/api:go_default_library",
"//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
], ],
) )
...@@ -32,4 +23,5 @@ filegroup( ...@@ -32,4 +23,5 @@ filegroup(
name = "all-srcs", name = "all-srcs",
srcs = [":package-srcs"], srcs = [":package-srcs"],
tags = ["automanaged"], tags = ["automanaged"],
visibility = ["//visibility:public"],
) )
...@@ -14,36 +14,27 @@ See the License for the specific language governing permissions and ...@@ -14,36 +14,27 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
// Package install installs the experimental API group, making it available as package scheme
// an option to all of the API encoding/decoding machinery.
package install
import ( import (
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/api" "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
) )
func init() { // Utility functions for the Kubelet's kubeletconfig API group
// TODO(mtaufen): probably want to create a kubelet scheme rather than reusing the api scheme, but need to ask lavalamp
Install(api.GroupFactoryRegistry, api.Registry, api.Scheme)
}
// Install registers the API group and adds types to a scheme // NewSchemeAndCodecs is a utility funciton that returns a Scheme and CodecFactory
func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { // that understand the types in the kubeletconfig API group.
if err := announced.NewGroupMetaFactory( func NewSchemeAndCodecs() (*runtime.Scheme, *serializer.CodecFactory, error) {
&announced.GroupMetaFactoryArgs{ scheme := runtime.NewScheme()
GroupName: kubeletconfig.GroupName, if err := kubeletconfig.AddToScheme(scheme); err != nil {
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version}, return nil, nil, err
AddInternalObjectsToScheme: kubeletconfig.AddToScheme, }
}, if err := v1alpha1.AddToScheme(scheme); err != nil {
announced.VersionToSchemeFunc{ return nil, nil, err
v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme,
},
).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil {
panic(err)
} }
codecs := serializer.NewCodecFactory(scheme)
return scheme, &codecs, nil
} }
...@@ -15,8 +15,8 @@ go_test( ...@@ -15,8 +15,8 @@ go_test(
], ],
library = ":go_default_library", library = ":go_default_library",
deps = [ deps = [
"//pkg/api:go_default_library",
"//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
"//pkg/kubelet/kubeletconfig/util/codec:go_default_library", "//pkg/kubelet/kubeletconfig/util/codec:go_default_library",
"//pkg/kubelet/kubeletconfig/util/test:go_default_library", "//pkg/kubelet/kubeletconfig/util/test:go_default_library",
...@@ -40,12 +40,14 @@ go_library( ...@@ -40,12 +40,14 @@ go_library(
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library",
"//pkg/kubelet/kubeletconfig/util/codec:go_default_library", "//pkg/kubelet/kubeletconfig/util/codec:go_default_library",
"//pkg/kubelet/kubeletconfig/util/log:go_default_library", "//pkg/kubelet/kubeletconfig/util/log:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library",
], ],
) )
......
...@@ -30,7 +30,7 @@ import ( ...@@ -30,7 +30,7 @@ import (
type Checkpoint interface { type Checkpoint interface {
// UID returns the UID of the config source object behind the Checkpoint // UID returns the UID of the config source object behind the Checkpoint
UID() string UID() string
// Parse parses the checkpoint into the internal KubeletConfiguration type // Parse extracts the KubeletConfiguration from the checkpoint, applies defaults, and converts to the internal type
Parse() (*kubeletconfig.KubeletConfiguration, error) Parse() (*kubeletconfig.KubeletConfiguration, error)
// Encode returns a []byte representation of the config source object behind the Checkpoint // Encode returns a []byte representation of the config source object behind the Checkpoint
Encode() ([]byte, error) Encode() ([]byte, error)
...@@ -56,6 +56,7 @@ func DecodeCheckpoint(data []byte) (Checkpoint, error) { ...@@ -56,6 +56,7 @@ func DecodeCheckpoint(data []byte) (Checkpoint, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to convert decoded object into a v1 ConfigMap, error: %v", err) return nil, fmt.Errorf("failed to convert decoded object into a v1 ConfigMap, error: %v", err)
} }
return NewConfigMapCheckpoint(cm) return NewConfigMapCheckpoint(cm)
} }
......
...@@ -30,20 +30,6 @@ import ( ...@@ -30,20 +30,6 @@ import (
utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test" utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test"
) )
// newUnsupportedEncoded returns an encoding of an object that does not have a Checkpoint implementation
func newUnsupportedEncoded(t *testing.T) []byte {
encoder, err := utilcodec.NewJSONEncoder(apiv1.GroupName)
if err != nil {
t.Fatalf("could not create an encoder, error: %v", err)
}
unsupported := &apiv1.Node{}
data, err := runtime.Encode(encoder, unsupported)
if err != nil {
t.Fatalf("could not encode object, error: %v", err)
}
return data
}
func TestDecodeCheckpoint(t *testing.T) { func TestDecodeCheckpoint(t *testing.T) {
// generate correct Checkpoint for v1/ConfigMap test case // generate correct Checkpoint for v1/ConfigMap test case
cm, err := NewConfigMapCheckpoint(&apiv1.ConfigMap{ObjectMeta: metav1.ObjectMeta{UID: types.UID("uid")}}) cm, err := NewConfigMapCheckpoint(&apiv1.ConfigMap{ObjectMeta: metav1.ObjectMeta{UID: types.UID("uid")}})
...@@ -87,3 +73,17 @@ func TestDecodeCheckpoint(t *testing.T) { ...@@ -87,3 +73,17 @@ func TestDecodeCheckpoint(t *testing.T) {
} }
} }
} }
// newUnsupportedEncoded returns an encoding of an object that does not have a Checkpoint implementation
func newUnsupportedEncoded(t *testing.T) []byte {
encoder, err := utilcodec.NewJSONEncoder(apiv1.GroupName)
if err != nil {
t.Fatalf("could not create an encoder, error: %v", err)
}
unsupported := &apiv1.Node{}
data, err := runtime.Encode(encoder, unsupported)
if err != nil {
t.Fatalf("could not encode object, error: %v", err)
}
return data
}
...@@ -21,7 +21,9 @@ import ( ...@@ -21,7 +21,9 @@ import (
apiv1 "k8s.io/api/core/v1" apiv1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
utilcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec" utilcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec"
) )
...@@ -29,7 +31,8 @@ const configMapConfigKey = "kubelet" ...@@ -29,7 +31,8 @@ const configMapConfigKey = "kubelet"
// configMapCheckpoint implements Checkpoint, backed by a v1/ConfigMap config source object // configMapCheckpoint implements Checkpoint, backed by a v1/ConfigMap config source object
type configMapCheckpoint struct { type configMapCheckpoint struct {
configMap *apiv1.ConfigMap kubeletCodecs *serializer.CodecFactory // codecs for the KubeletConfiguration
configMap *apiv1.ConfigMap
} }
// NewConfigMapCheckpoint returns a Checkpoint backed by `cm`. `cm` must be non-nil // NewConfigMapCheckpoint returns a Checkpoint backed by `cm`. `cm` must be non-nil
...@@ -40,7 +43,13 @@ func NewConfigMapCheckpoint(cm *apiv1.ConfigMap) (Checkpoint, error) { ...@@ -40,7 +43,13 @@ func NewConfigMapCheckpoint(cm *apiv1.ConfigMap) (Checkpoint, error) {
} else if len(cm.ObjectMeta.UID) == 0 { } else if len(cm.ObjectMeta.UID) == 0 {
return nil, fmt.Errorf("ConfigMap must have a UID to be treated as a Checkpoint") return nil, fmt.Errorf("ConfigMap must have a UID to be treated as a Checkpoint")
} }
return &configMapCheckpoint{cm}, nil
_, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs()
if err != nil {
return nil, err
}
return &configMapCheckpoint{kubeletCodecs, cm}, nil
} }
// UID returns the UID of a configMapCheckpoint // UID returns the UID of a configMapCheckpoint
...@@ -48,25 +57,23 @@ func (c *configMapCheckpoint) UID() string { ...@@ -48,25 +57,23 @@ func (c *configMapCheckpoint) UID() string {
return string(c.configMap.UID) return string(c.configMap.UID)
} }
// implements Parse for v1/ConfigMap checkpoints // Parse extracts the KubeletConfiguration from v1/ConfigMap checkpoints, applies defaults, and converts to the internal type
func (c *configMapCheckpoint) Parse() (*kubeletconfig.KubeletConfiguration, error) { func (c *configMapCheckpoint) Parse() (*kubeletconfig.KubeletConfiguration, error) {
const emptyCfgErr = "config was empty, but some parameters are required" const emptyCfgErr = "config was empty, but some parameters are required"
cm := c.configMap if len(c.configMap.Data) == 0 {
if len(cm.Data) == 0 {
return nil, fmt.Errorf(emptyCfgErr) return nil, fmt.Errorf(emptyCfgErr)
} }
// TODO(mtaufen): Once the KubeletConfiguration type is decomposed, extend this to a key for each sub-object // TODO(mtaufen): Once the KubeletConfiguration type is decomposed, extend this to a key for each sub-object
config, ok := cm.Data[configMapConfigKey] config, ok := c.configMap.Data[configMapConfigKey]
if !ok { if !ok {
return nil, fmt.Errorf("key %q not found in ConfigMap", configMapConfigKey) return nil, fmt.Errorf("key %q not found in ConfigMap", configMapConfigKey)
} else if len(config) == 0 { } else if len(config) == 0 {
return nil, fmt.Errorf(emptyCfgErr) return nil, fmt.Errorf(emptyCfgErr)
} }
return utilcodec.DecodeKubeletConfiguration([]byte(config)) return utilcodec.DecodeKubeletConfiguration(c.kubeletCodecs, []byte(config))
} }
// Encode encodes a configMapCheckpoint // Encode encodes a configMapCheckpoint
......
...@@ -26,8 +26,8 @@ import ( ...@@ -26,8 +26,8 @@ import (
apiequality "k8s.io/apimachinery/pkg/api/equality" apiequality "k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1" kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test" utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test"
) )
...@@ -66,9 +66,15 @@ func TestNewConfigMapCheckpoint(t *testing.T) { ...@@ -66,9 +66,15 @@ func TestNewConfigMapCheckpoint(t *testing.T) {
} }
func TestConfigMapCheckpointUID(t *testing.T) { func TestConfigMapCheckpointUID(t *testing.T) {
_, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
cases := []string{"", "uid", "376dfb73-56db-11e7-a01e-42010a800002"} cases := []string{"", "uid", "376dfb73-56db-11e7-a01e-42010a800002"}
for _, uidIn := range cases { for _, uidIn := range cases {
cpt := &configMapCheckpoint{ cpt := &configMapCheckpoint{
kubeletCodecs,
&apiv1.ConfigMap{ &apiv1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{UID: types.UID(uidIn)}, ObjectMeta: metav1.ObjectMeta{UID: types.UID(uidIn)},
}, },
...@@ -82,11 +88,16 @@ func TestConfigMapCheckpointUID(t *testing.T) { ...@@ -82,11 +88,16 @@ func TestConfigMapCheckpointUID(t *testing.T) {
} }
func TestConfigMapCheckpointParse(t *testing.T) { func TestConfigMapCheckpointParse(t *testing.T) {
kubeletScheme, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
// get the built-in default configuration // get the built-in default configuration
external := &kubeletconfigv1alpha1.KubeletConfiguration{} external := &kubeletconfigv1alpha1.KubeletConfiguration{}
api.Scheme.Default(external) kubeletScheme.Default(external)
defaultConfig := &kubeletconfig.KubeletConfiguration{} defaultConfig := &kubeletconfig.KubeletConfiguration{}
err := api.Scheme.Convert(external, defaultConfig, nil) err = kubeletScheme.Convert(external, defaultConfig, nil)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -123,7 +134,7 @@ apiVersion: kubeletconfig/v1alpha1`}}, defaultConfig, ""}, ...@@ -123,7 +134,7 @@ apiVersion: kubeletconfig/v1alpha1`}}, defaultConfig, ""},
"kubelet": `{"kind":"KubeletConfiguration","apiVersion":"kubeletconfig/v1alpha1"}`}}, defaultConfig, ""}, "kubelet": `{"kind":"KubeletConfiguration","apiVersion":"kubeletconfig/v1alpha1"}`}}, defaultConfig, ""},
} }
for _, c := range cases { for _, c := range cases {
cpt := &configMapCheckpoint{c.cm} cpt := &configMapCheckpoint{kubeletCodecs, c.cm}
kc, err := cpt.Parse() kc, err := cpt.Parse()
if utiltest.SkipRest(t, c.desc, err, c.err) { if utiltest.SkipRest(t, c.desc, err, c.err) {
continue continue
...@@ -136,6 +147,11 @@ apiVersion: kubeletconfig/v1alpha1`}}, defaultConfig, ""}, ...@@ -136,6 +147,11 @@ apiVersion: kubeletconfig/v1alpha1`}}, defaultConfig, ""},
} }
func TestConfigMapCheckpointEncode(t *testing.T) { func TestConfigMapCheckpointEncode(t *testing.T) {
_, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
// only one case, based on output from the existing encoder, and since // only one case, based on output from the existing encoder, and since
// this is hard to test (key order isn't guaranteed), we should probably // this is hard to test (key order isn't guaranteed), we should probably
// just stick to this test case and mostly rely on the round-trip test. // just stick to this test case and mostly rely on the round-trip test.
...@@ -146,7 +162,7 @@ func TestConfigMapCheckpointEncode(t *testing.T) { ...@@ -146,7 +162,7 @@ func TestConfigMapCheckpointEncode(t *testing.T) {
}{ }{
// we expect Checkpoints to be encoded as a json representation of the underlying API object // we expect Checkpoints to be encoded as a json representation of the underlying API object
{"one-key", {"one-key",
&configMapCheckpoint{&apiv1.ConfigMap{ &configMapCheckpoint{kubeletCodecs, &apiv1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "one-key"}, ObjectMeta: metav1.ObjectMeta{Name: "one-key"},
Data: map[string]string{"one": ""}}}, Data: map[string]string{"one": ""}}},
`{"kind":"ConfigMap","apiVersion":"v1","metadata":{"name":"one-key","creationTimestamp":null},"data":{"one":""}} `{"kind":"ConfigMap","apiVersion":"v1","metadata":{"name":"one-key","creationTimestamp":null},"data":{"one":""}}
...@@ -166,6 +182,11 @@ func TestConfigMapCheckpointEncode(t *testing.T) { ...@@ -166,6 +182,11 @@ func TestConfigMapCheckpointEncode(t *testing.T) {
} }
func TestConfigMapCheckpointRoundTrip(t *testing.T) { func TestConfigMapCheckpointRoundTrip(t *testing.T) {
_, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
cases := []struct { cases := []struct {
desc string desc string
cpt *configMapCheckpoint cpt *configMapCheckpoint
...@@ -173,7 +194,7 @@ func TestConfigMapCheckpointRoundTrip(t *testing.T) { ...@@ -173,7 +194,7 @@ func TestConfigMapCheckpointRoundTrip(t *testing.T) {
}{ }{
// empty data // empty data
{"empty data", {"empty data",
&configMapCheckpoint{&apiv1.ConfigMap{ &configMapCheckpoint{kubeletCodecs, &apiv1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "empty-data-sha256-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", Name: "empty-data-sha256-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
UID: "uid", UID: "uid",
...@@ -182,7 +203,7 @@ func TestConfigMapCheckpointRoundTrip(t *testing.T) { ...@@ -182,7 +203,7 @@ func TestConfigMapCheckpointRoundTrip(t *testing.T) {
""}, ""},
// two keys // two keys
{"two keys", {"two keys",
&configMapCheckpoint{&apiv1.ConfigMap{ &configMapCheckpoint{kubeletCodecs, &apiv1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "two-keys-sha256-2bff03d6249c8a9dc9a1436d087c124741361ccfac6615b81b67afcff5c42431", Name: "two-keys-sha256-2bff03d6249c8a9dc9a1436d087c124741361ccfac6615b81b67afcff5c42431",
UID: "uid", UID: "uid",
...@@ -191,7 +212,7 @@ func TestConfigMapCheckpointRoundTrip(t *testing.T) { ...@@ -191,7 +212,7 @@ func TestConfigMapCheckpointRoundTrip(t *testing.T) {
""}, ""},
// missing uid // missing uid
{"missing uid", {"missing uid",
&configMapCheckpoint{&apiv1.ConfigMap{ &configMapCheckpoint{kubeletCodecs, &apiv1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "two-keys-sha256-2bff03d6249c8a9dc9a1436d087c124741361ccfac6615b81b67afcff5c42431", Name: "two-keys-sha256-2bff03d6249c8a9dc9a1436d087c124741361ccfac6615b81b67afcff5c42431",
UID: "", UID: "",
......
...@@ -113,7 +113,6 @@ func (r *remoteConfigMap) UID() string { ...@@ -113,7 +113,6 @@ func (r *remoteConfigMap) UID() string {
func (r *remoteConfigMap) Download(client clientset.Interface) (Checkpoint, string, error) { func (r *remoteConfigMap) Download(client clientset.Interface) (Checkpoint, string, error) {
var reason string var reason string
uid := string(r.source.ConfigMapRef.UID) uid := string(r.source.ConfigMapRef.UID)
utillog.Infof("attempting to download ConfigMap with UID %q", uid) utillog.Infof("attempting to download ConfigMap with UID %q", uid)
...@@ -131,8 +130,14 @@ func (r *remoteConfigMap) Download(client clientset.Interface) (Checkpoint, stri ...@@ -131,8 +130,14 @@ func (r *remoteConfigMap) Download(client clientset.Interface) (Checkpoint, stri
return nil, reason, fmt.Errorf(reason) return nil, reason, fmt.Errorf(reason)
} }
checkpoint, err := NewConfigMapCheckpoint(cm)
if err != nil {
reason = fmt.Sprintf("invalid downloaded object")
return nil, reason, fmt.Errorf("%s, error: %v", reason, err)
}
utillog.Infof("successfully downloaded ConfigMap with UID %q", uid) utillog.Infof("successfully downloaded ConfigMap with UID %q", uid)
return &configMapCheckpoint{cm}, "", nil return checkpoint, "", nil
} }
func (r *remoteConfigMap) Encode() ([]byte, error) { func (r *remoteConfigMap) Encode() ([]byte, error) {
......
...@@ -26,6 +26,7 @@ import ( ...@@ -26,6 +26,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
fakeclient "k8s.io/client-go/kubernetes/fake" fakeclient "k8s.io/client-go/kubernetes/fake"
kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test" utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test"
) )
...@@ -92,6 +93,11 @@ func TestRemoteConfigMapUID(t *testing.T) { ...@@ -92,6 +93,11 @@ func TestRemoteConfigMapUID(t *testing.T) {
} }
func TestRemoteConfigMapDownload(t *testing.T) { func TestRemoteConfigMapDownload(t *testing.T) {
_, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
cm := &apiv1.ConfigMap{ cm := &apiv1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "name", Name: "name",
...@@ -118,7 +124,7 @@ func TestRemoteConfigMapDownload(t *testing.T) { ...@@ -118,7 +124,7 @@ func TestRemoteConfigMapDownload(t *testing.T) {
// successful download // successful download
{"object exists and reference is correct", {"object exists and reference is correct",
&remoteConfigMap{&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}}, &remoteConfigMap{&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}},
&configMapCheckpoint{cm}, ""}, &configMapCheckpoint{kubeletCodecs, cm}, ""},
} }
for _, c := range cases { for _, c := range cases {
......
...@@ -10,8 +10,10 @@ go_library( ...@@ -10,8 +10,10 @@ go_library(
srcs = ["configfiles.go"], srcs = ["configfiles.go"],
deps = [ deps = [
"//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library",
"//pkg/kubelet/kubeletconfig/util/codec:go_default_library", "//pkg/kubelet/kubeletconfig/util/codec:go_default_library",
"//pkg/kubelet/kubeletconfig/util/filesystem:go_default_library", "//pkg/kubelet/kubeletconfig/util/filesystem:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
], ],
) )
......
...@@ -20,7 +20,9 @@ import ( ...@@ -20,7 +20,9 @@ import (
"fmt" "fmt"
"path/filepath" "path/filepath"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
utilcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec" utilcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec"
utilfs "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/filesystem" utilfs "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/filesystem"
) )
...@@ -35,16 +37,24 @@ type Loader interface { ...@@ -35,16 +37,24 @@ type Loader interface {
type fsLoader struct { type fsLoader struct {
// fs is the filesystem where the config files exist; can be mocked for testing // fs is the filesystem where the config files exist; can be mocked for testing
fs utilfs.Filesystem fs utilfs.Filesystem
// kubeletCodecs is the scheme used to decode config files
kubeletCodecs *serializer.CodecFactory
// configDir is the absolute path to the directory containing the configuration files // configDir is the absolute path to the directory containing the configuration files
configDir string configDir string
} }
// NewFSLoader returns a Loader that loads a KubeletConfiguration from the files in `configDir` // NewFSLoader returns a Loader that loads a KubeletConfiguration from the files in `configDir`
func NewFSLoader(fs utilfs.Filesystem, configDir string) Loader { func NewFSLoader(fs utilfs.Filesystem, configDir string) (Loader, error) {
return &fsLoader{ _, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs()
fs: fs, if err != nil {
configDir: configDir, return nil, err
} }
return &fsLoader{
fs: fs,
kubeletCodecs: kubeletCodecs,
configDir: configDir,
}, nil
} }
func (loader *fsLoader) Load() (*kubeletconfig.KubeletConfiguration, error) { func (loader *fsLoader) Load() (*kubeletconfig.KubeletConfiguration, error) {
...@@ -62,5 +72,5 @@ func (loader *fsLoader) Load() (*kubeletconfig.KubeletConfiguration, error) { ...@@ -62,5 +72,5 @@ func (loader *fsLoader) Load() (*kubeletconfig.KubeletConfiguration, error) {
return nil, fmt.Errorf(errfmt, fmt.Errorf("config file was empty, but some parameters are required")) return nil, fmt.Errorf(errfmt, fmt.Errorf("config file was empty, but some parameters are required"))
} }
return utilcodec.DecodeKubeletConfiguration(data) return utilcodec.DecodeKubeletConfiguration(loader.kubeletCodecs, data)
} }
...@@ -53,7 +53,7 @@ const ( ...@@ -53,7 +53,7 @@ const (
// - validates configuration // - validates configuration
// - monitors for potential crash-loops caused by new configurations // - monitors for potential crash-loops caused by new configurations
// - tracks the last-known-good configuration, and rolls-back to last-known-good when necessary // - tracks the last-known-good configuration, and rolls-back to last-known-good when necessary
// For more information, see the proposal: https://github.com/kubernetes/kubernetes/pull/29459 // For more information, see the proposal: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/dynamic-kubelet-configuration.md
type Controller struct { type Controller struct {
// dynamicConfig, if true, indicates that we should sync config from the API server // dynamicConfig, if true, indicates that we should sync config from the API server
dynamicConfig bool dynamicConfig bool
...@@ -90,12 +90,19 @@ type Controller struct { ...@@ -90,12 +90,19 @@ type Controller struct {
// If the `initConfigDir` is an empty string, skips trying to load the init config. // If the `initConfigDir` is an empty string, skips trying to load the init config.
// If the `dynamicConfigDir` is an empty string, skips trying to load checkpoints or download new config, // If the `dynamicConfigDir` is an empty string, skips trying to load checkpoints or download new config,
// but will still sync the ConfigOK condition if you call StartSync with a non-nil client. // but will still sync the ConfigOK condition if you call StartSync with a non-nil client.
func NewController(initConfigDir string, dynamicConfigDir string, defaultConfig *kubeletconfig.KubeletConfiguration) *Controller { func NewController(initConfigDir string,
dynamicConfigDir string,
defaultConfig *kubeletconfig.KubeletConfiguration) (*Controller, error) {
var err error
fs := utilfs.DefaultFs{} fs := utilfs.DefaultFs{}
var initLoader configfiles.Loader var initLoader configfiles.Loader
if len(initConfigDir) > 0 { if len(initConfigDir) > 0 {
initLoader = configfiles.NewFSLoader(fs, initConfigDir) initLoader, err = configfiles.NewFSLoader(fs, initConfigDir)
if err != nil {
return nil, err
}
} }
dynamicConfig := false dynamicConfig := false
if len(dynamicConfigDir) > 0 { if len(dynamicConfigDir) > 0 {
...@@ -120,7 +127,7 @@ func NewController(initConfigDir string, dynamicConfigDir string, defaultConfig ...@@ -120,7 +127,7 @@ func NewController(initConfigDir string, dynamicConfigDir string, defaultConfig
badConfigTracker: badconfig.NewFsTracker(fs, filepath.Join(dynamicConfigDir, badConfigTrackingDir, kubeletVersion)), badConfigTracker: badconfig.NewFsTracker(fs, filepath.Join(dynamicConfigDir, badConfigTrackingDir, kubeletVersion)),
startupTracker: startups.NewFsTracker(fs, filepath.Join(dynamicConfigDir, startupTrackingDir, kubeletVersion)), startupTracker: startups.NewFsTracker(fs, filepath.Join(dynamicConfigDir, startupTrackingDir, kubeletVersion)),
initLoader: initLoader, initLoader: initLoader,
} }, nil
} }
// Bootstrap attempts to return a valid KubeletConfiguration based on the configuration of the Controller, // Bootstrap attempts to return a valid KubeletConfiguration based on the configuration of the Controller,
......
...@@ -12,9 +12,8 @@ go_library( ...@@ -12,9 +12,8 @@ go_library(
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/install:go_default_library", "//pkg/api/install:go_default_library",
"//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/install:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
], ],
) )
......
...@@ -21,13 +21,11 @@ import ( ...@@ -21,13 +21,11 @@ import (
// ensure the core apis are installed // ensure the core apis are installed
_ "k8s.io/kubernetes/pkg/api/install" _ "k8s.io/kubernetes/pkg/api/install"
// ensure the kubeletconfig apis are installed
_ "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/install"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
) )
// TODO(mtaufen): allow an encoder to be injected into checkpoint objects at creation time? (then we could ultimately instantiate only one encoder) // TODO(mtaufen): allow an encoder to be injected into checkpoint objects at creation time? (then we could ultimately instantiate only one encoder)
...@@ -50,28 +48,18 @@ func NewJSONEncoder(groupName string) (runtime.Encoder, error) { ...@@ -50,28 +48,18 @@ func NewJSONEncoder(groupName string) (runtime.Encoder, error) {
return api.Codecs.EncoderForVersion(info.Serializer, versions[0]), nil return api.Codecs.EncoderForVersion(info.Serializer, versions[0]), nil
} }
// DecodeKubeletConfiguration decodes an encoded (v1alpha1) KubeletConfiguration object to the internal type // DecodeKubeletConfiguration decodes a serialized KubeletConfiguration to the internal type
func DecodeKubeletConfiguration(data []byte) (*kubeletconfig.KubeletConfiguration, error) { func DecodeKubeletConfiguration(kubeletCodecs *serializer.CodecFactory, data []byte) (*kubeletconfig.KubeletConfiguration, error) {
// decode the object, note we use the external version scheme to decode, because users provide the external version // the UniversalDecoder runs defaulting and returns the internal type by default
obj, err := runtime.Decode(api.Codecs.UniversalDecoder(kubeletconfigv1alpha1.SchemeGroupVersion), data) obj, gvk, err := kubeletCodecs.UniversalDecoder().Decode(data, nil, nil)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to decode, error: %v", err) return nil, fmt.Errorf("failed to decode, error: %v", err)
} }
externalKC, ok := obj.(*kubeletconfigv1alpha1.KubeletConfiguration) internalKC, ok := obj.(*kubeletconfig.KubeletConfiguration)
if !ok { if !ok {
return nil, fmt.Errorf("failed to cast object to KubeletConfiguration, object: %#v", obj) return nil, fmt.Errorf("failed to cast object to KubeletConfiguration, unexpected type: %v", gvk)
} }
// TODO(mtaufen): confirm whether api.Codecs.UniversalDecoder runs the defaulting, which would make this redundant
// run the defaulter on the decoded configuration before converting to internal type
api.Scheme.Default(externalKC)
// convert to internal type
internalKC := &kubeletconfig.KubeletConfiguration{}
err = api.Scheme.Convert(externalKC, internalKC, nil)
if err != nil {
return nil, err
}
return internalKC, nil return internalKC, nil
} }
...@@ -30,6 +30,7 @@ go_library( ...@@ -30,6 +30,7 @@ go_library(
"//pkg/kubelet/apis/cri:go_default_library", "//pkg/kubelet/apis/cri:go_default_library",
"//pkg/kubelet/apis/cri/v1alpha1/runtime:go_default_library", "//pkg/kubelet/apis/cri/v1alpha1/runtime:go_default_library",
"//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
"//pkg/kubelet/apis/stats/v1alpha1:go_default_library", "//pkg/kubelet/apis/stats/v1alpha1:go_default_library",
"//pkg/kubelet/metrics:go_default_library", "//pkg/kubelet/metrics:go_default_library",
......
...@@ -37,6 +37,7 @@ import ( ...@@ -37,6 +37,7 @@ import (
"k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/kubernetes/scheme"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1" kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
kubeletmetrics "k8s.io/kubernetes/pkg/kubelet/metrics" kubeletmetrics "k8s.io/kubernetes/pkg/kubelet/metrics"
...@@ -262,7 +263,7 @@ func makeKubeletConfigMap(internalKC *kubeletconfig.KubeletConfiguration) *v1.Co ...@@ -262,7 +263,7 @@ func makeKubeletConfigMap(internalKC *kubeletconfig.KubeletConfiguration) *v1.Co
externalKC := &kubeletconfigv1alpha1.KubeletConfiguration{} externalKC := &kubeletconfigv1alpha1.KubeletConfiguration{}
api.Scheme.Convert(internalKC, externalKC, nil) api.Scheme.Convert(internalKC, externalKC, nil)
encoder, err := newJSONEncoder(kubeletconfig.GroupName) encoder, err := newKubeletConfigJSONEncoder()
framework.ExpectNoError(err) framework.ExpectNoError(err)
data, err := runtime.Encode(encoder, externalKC) data, err := runtime.Encode(encoder, externalKC)
...@@ -310,21 +311,18 @@ func logKubeletMetrics(metricKeys ...string) { ...@@ -310,21 +311,18 @@ func logKubeletMetrics(metricKeys ...string) {
} }
} }
func newJSONEncoder(groupName string) (runtime.Encoder, error) { func newKubeletConfigJSONEncoder() (runtime.Encoder, error) {
// encode to json _, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs()
if err != nil {
return nil, err
}
mediaType := "application/json" mediaType := "application/json"
info, ok := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), mediaType) info, ok := runtime.SerializerInfoForMediaType(kubeletCodecs.SupportedMediaTypes(), mediaType)
if !ok { if !ok {
return nil, fmt.Errorf("unsupported media type %q", mediaType) return nil, fmt.Errorf("unsupported media type %q", mediaType)
} }
return kubeletCodecs.EncoderForVersion(info.Serializer, kubeletconfigv1alpha1.SchemeGroupVersion), nil
versions := api.Registry.EnabledVersionsForGroup(groupName)
if len(versions) == 0 {
return nil, fmt.Errorf("no enabled versions for group %q", groupName)
}
// the "best" version supposedly comes first in the list returned from api.Registry.EnabledVersionsForGroup
return api.Codecs.EncoderForVersion(info.Serializer, versions[0]), nil
} }
// runCommand runs the cmd and returns the combined stdout and stderr, or an // runCommand runs the cmd and returns the combined stdout and stderr, or an
......
...@@ -434,10 +434,6 @@ var ephemeralWhiteList = createEphemeralWhiteList( ...@@ -434,10 +434,6 @@ var ephemeralWhiteList = createEphemeralWhiteList(
gvr("componentconfig", "v1alpha1", "kubeproxyconfigurations"), // not stored in etcd gvr("componentconfig", "v1alpha1", "kubeproxyconfigurations"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1
gvr("kubeletconfig", "v1alpha1", "kubeletconfigurations"), // not stored in etcd
// --
// k8s.io/kubernetes/pkg/apis/extensions/v1beta1 // k8s.io/kubernetes/pkg/apis/extensions/v1beta1
gvr("extensions", "v1beta1", "deploymentrollbacks"), // used to rollback deployment, not stored in etcd gvr("extensions", "v1beta1", "deploymentrollbacks"), // used to rollback deployment, not stored in etcd
gvr("extensions", "v1beta1", "replicationcontrollerdummies"), // not stored in etcd gvr("extensions", "v1beta1", "replicationcontrollerdummies"), // not stored in etcd
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment