mirror of https://github.com/k3s-io/k3s
166 lines
7.6 KiB
Go
166 lines
7.6 KiB
Go
/*
|
|
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
|
|
}
|