| /* |
| Copyright 2018 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 componentconfigs |
| |
| import ( |
| "k8s.io/apimachinery/pkg/runtime" |
| "k8s.io/apimachinery/pkg/runtime/schema" |
| "k8s.io/apimachinery/pkg/util/validation/field" |
| "k8s.io/apimachinery/pkg/util/version" |
| clientset "k8s.io/client-go/kubernetes" |
| kubeproxyconfigv1alpha1 "k8s.io/kube-proxy/config/v1alpha1" |
| kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1" |
| kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" |
| kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" |
| kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" |
| kubeletconfigv1beta1scheme "k8s.io/kubernetes/pkg/kubelet/apis/config/v1beta1" |
| kubeproxyconfig "k8s.io/kubernetes/pkg/proxy/apis/config" |
| kubeproxyconfigv1alpha1scheme "k8s.io/kubernetes/pkg/proxy/apis/config/v1alpha1" |
| ) |
| |
| // AddToSchemeFunc is a function that adds known types and API GroupVersions to a scheme |
| type AddToSchemeFunc func(*runtime.Scheme) error |
| |
| // Registration is an object for registering a Kubernetes ComponentConfig type to be recognized and handled by kubeadm |
| type Registration struct { |
| // MarshalGroupVersion is the preferred external API version to use when marshalling the ComponentConfig |
| MarshalGroupVersion schema.GroupVersion |
| // AddToSchemeFuncs are a set of functions that register APIs to the scheme |
| AddToSchemeFuncs []AddToSchemeFunc |
| // DefaulterFunc is a function that based on the internal kubeadm configuration defaults the ComponentConfig struct |
| DefaulterFunc func(*kubeadmapi.ClusterConfiguration) |
| // ValidateFunc is a function that should validate the ComponentConfig type embedded in the internal kubeadm config struct |
| ValidateFunc func(*kubeadmapi.ClusterConfiguration, *field.Path) field.ErrorList |
| // EmptyValue holds a pointer to an empty struct of the internal ComponentConfig type |
| EmptyValue runtime.Object |
| // GetFromInternalConfig returns the pointer to the ComponentConfig API object from the internal kubeadm config struct |
| GetFromInternalConfig func(*kubeadmapi.ClusterConfiguration) (runtime.Object, bool) |
| // SetToInternalConfig sets the pointer to a ComponentConfig API object embedded in the internal kubeadm config struct |
| SetToInternalConfig func(runtime.Object, *kubeadmapi.ClusterConfiguration) bool |
| // GetFromConfigMap returns the pointer to the ComponentConfig API object read from the config map stored in the cluster |
| GetFromConfigMap func(clientset.Interface, *version.Version) (runtime.Object, error) |
| } |
| |
| // Marshal marshals obj to bytes for the current Registration |
| func (r Registration) Marshal(obj runtime.Object) ([]byte, error) { |
| return kubeadmutil.MarshalToYamlForCodecs(obj, r.MarshalGroupVersion, Codecs) |
| } |
| |
| // Unmarshal unmarshals the bytes to a runtime.Object using the Codecs registered in this Scheme |
| func (r Registration) Unmarshal(fileContent []byte) (runtime.Object, error) { |
| // Do a deepcopy of the empty value so we don't mutate it, which could lead to strange errors |
| obj := r.EmptyValue.DeepCopyObject() |
| |
| // Decode the file content into obj which is a pointer to an empty struct of the internal ComponentConfig |
| if err := unmarshalObject(obj, fileContent); err != nil { |
| return nil, err |
| } |
| return obj, nil |
| } |
| |
| func unmarshalObject(obj runtime.Object, fileContent []byte) error { |
| // Decode the file content using the componentconfig Codecs that knows about all APIs |
| if err := runtime.DecodeInto(Codecs.UniversalDecoder(), fileContent, obj); err != nil { |
| return err |
| } |
| return nil |
| } |
| |
| const ( |
| // KubeletConfigurationKind is the kind for the kubelet ComponentConfig |
| KubeletConfigurationKind RegistrationKind = "KubeletConfiguration" |
| // KubeProxyConfigurationKind is the kind for the kubelet ComponentConfig |
| KubeProxyConfigurationKind RegistrationKind = "KubeProxyConfiguration" |
| ) |
| |
| // RegistrationKind is a string type to ensure not any string can be a key in the Registrations map |
| type RegistrationKind string |
| |
| // Registrations holds a set of ComponentConfig Registration objects, where the map key is the kind |
| type Registrations map[RegistrationKind]Registration |
| |
| // Known contains the known ComponentConfig registrations to kubeadm |
| var Known Registrations = map[RegistrationKind]Registration{ |
| KubeProxyConfigurationKind: { |
| // TODO: When a beta version of the kube-proxy ComponentConfig API is available, start using it |
| MarshalGroupVersion: kubeproxyconfigv1alpha1.SchemeGroupVersion, |
| // AddToSchemeFuncs must use v1alpha1scheme defined in k8s.io/kubernetes, because the schema defined in k8s.io/kube-proxy doesn't have defaulting functions |
| AddToSchemeFuncs: []AddToSchemeFunc{kubeproxyconfig.AddToScheme, kubeproxyconfigv1alpha1scheme.AddToScheme}, |
| DefaulterFunc: DefaultKubeProxyConfiguration, |
| ValidateFunc: ValidateKubeProxyConfiguration, |
| EmptyValue: &kubeproxyconfig.KubeProxyConfiguration{}, |
| GetFromInternalConfig: func(cfg *kubeadmapi.ClusterConfiguration) (runtime.Object, bool) { |
| return cfg.ComponentConfigs.KubeProxy, cfg.ComponentConfigs.KubeProxy != nil |
| }, |
| SetToInternalConfig: func(obj runtime.Object, cfg *kubeadmapi.ClusterConfiguration) bool { |
| kubeproxyConfig, ok := obj.(*kubeproxyconfig.KubeProxyConfiguration) |
| if ok { |
| cfg.ComponentConfigs.KubeProxy = kubeproxyConfig |
| } |
| return ok |
| }, |
| GetFromConfigMap: GetFromKubeProxyConfigMap, |
| }, |
| KubeletConfigurationKind: { |
| MarshalGroupVersion: kubeletconfigv1beta1.SchemeGroupVersion, |
| // PAddToSchemeFuncs must use v1alpha1scheme defined in k8s.io/kubernetes, because the schema defined in k8s.io/kubelet doesn't have defaulting functions |
| AddToSchemeFuncs: []AddToSchemeFunc{kubeletconfig.AddToScheme, kubeletconfigv1beta1scheme.AddToScheme}, |
| DefaulterFunc: DefaultKubeletConfiguration, |
| ValidateFunc: ValidateKubeletConfiguration, |
| EmptyValue: &kubeletconfig.KubeletConfiguration{}, |
| GetFromInternalConfig: func(cfg *kubeadmapi.ClusterConfiguration) (runtime.Object, bool) { |
| return cfg.ComponentConfigs.Kubelet, cfg.ComponentConfigs.Kubelet != nil |
| }, |
| SetToInternalConfig: func(obj runtime.Object, cfg *kubeadmapi.ClusterConfiguration) bool { |
| kubeletConfig, ok := obj.(*kubeletconfig.KubeletConfiguration) |
| if ok { |
| cfg.ComponentConfigs.Kubelet = kubeletConfig |
| } |
| return ok |
| }, |
| GetFromConfigMap: GetFromKubeletConfigMap, |
| }, |
| } |
| |
| // AddToScheme adds all the known ComponentConfig API types referenced in the Registrations object to the scheme |
| func (rs *Registrations) AddToScheme(scheme *runtime.Scheme) error { |
| for _, registration := range *rs { |
| for _, addToSchemeFunc := range registration.AddToSchemeFuncs { |
| if err := addToSchemeFunc(scheme); err != nil { |
| return err |
| } |
| } |
| } |
| return nil |
| } |
| |
| // Default applies to the ComponentConfig defaults to the internal kubeadm API type |
| func (rs *Registrations) Default(internalcfg *kubeadmapi.ClusterConfiguration) { |
| for _, registration := range *rs { |
| registration.DefaulterFunc(internalcfg) |
| } |
| } |
| |
| // Validate validates the ComponentConfig parts of the internal kubeadm API type |
| func (rs *Registrations) Validate(internalcfg *kubeadmapi.ClusterConfiguration) field.ErrorList { |
| allErrs := field.ErrorList{} |
| for kind, registration := range *rs { |
| allErrs = append(allErrs, registration.ValidateFunc(internalcfg, field.NewPath(string(kind)))...) |
| } |
| return allErrs |
| } |