Remove the ComponentConfig structs from the external v1alpha3 API. Use the new componentconfigs pkg for validation and conversion

This commit is contained in:
Lucas Käldström 2018-07-08 21:31:35 +03:00
parent f96ada0c04
commit 5aef95ebe1
No known key found for this signature in database
GPG Key ID: 3FA3783D77751514
7 changed files with 84 additions and 181 deletions

View File

@ -17,6 +17,8 @@ limitations under the License.
package kubeadm
import (
fuzz "github.com/google/gofuzz"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
@ -42,6 +44,7 @@ type MasterConfiguration struct {
NodeRegistration NodeRegistrationOptions
// ComponentConfigs holds internal ComponentConfig struct types known to kubeadm, should long-term only exist in the internal kubeadm API
// +k8s:conversion-gen=false
ComponentConfigs ComponentConfigs
// Cluster-wide configuration
@ -117,6 +120,12 @@ type ComponentConfigs struct {
KubeProxy *kubeproxyconfig.KubeProxyConfiguration
}
// Fuzz is a dummy function here to get the roundtrip tests working in cmd/kubeadm/app/apis/kubeadm/fuzzer working.
// This makes the fuzzer not go and randomize all fields in the ComponentConfigs struct, as that wouldn't work for
// a roundtrip. A roundtrip to the v1alpha3 API obviously doesn't work as it's not stored there at all. With this,
// the roundtrip is considered valid, as semi-static values are set and preserved during a roundtrip.
func (cc ComponentConfigs) Fuzz(c fuzz.Continue) {}
// API struct contains elements of API server address.
type API struct {
// AdvertiseAddress sets the IP address for the API server to advertise.

View File

@ -19,11 +19,10 @@ package v1alpha2
import (
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
kubeletconfigscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
"k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig"
kubeproxyconfigscheme "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/scheme"
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
)
@ -37,7 +36,7 @@ func Convert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration(in *Mas
out.ComponentConfigs.KubeProxy = &kubeproxyconfig.KubeProxyConfiguration{}
}
if err := kubeproxyconfigscheme.Scheme.Convert(in.KubeProxy.Config, out.ComponentConfigs.KubeProxy, nil); err != nil {
if err := componentconfigs.Scheme.Convert(in.KubeProxy.Config, out.ComponentConfigs.KubeProxy, nil); err != nil {
return err
}
}
@ -46,12 +45,7 @@ func Convert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration(in *Mas
out.ComponentConfigs.Kubelet = &kubeletconfig.KubeletConfiguration{}
}
scheme, _, err := kubeletconfigscheme.NewSchemeAndCodecs()
if err != nil {
return err
}
if err := scheme.Convert(in.KubeletConfiguration.BaseConfig, out.ComponentConfigs.Kubelet, nil); err != nil {
if err := componentconfigs.Scheme.Convert(in.KubeletConfiguration.BaseConfig, out.ComponentConfigs.Kubelet, nil); err != nil {
return err
}
}
@ -69,7 +63,7 @@ func Convert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration(in *kub
out.KubeProxy.Config = &kubeproxyconfigv1alpha1.KubeProxyConfiguration{}
}
if err := kubeproxyconfigscheme.Scheme.Convert(in.ComponentConfigs.KubeProxy, out.KubeProxy.Config, nil); err != nil {
if err := componentconfigs.Scheme.Convert(in.ComponentConfigs.KubeProxy, out.KubeProxy.Config, nil); err != nil {
return err
}
}
@ -78,12 +72,7 @@ func Convert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration(in *kub
out.KubeletConfiguration.BaseConfig = &kubeletconfigv1beta1.KubeletConfiguration{}
}
scheme, _, err := kubeletconfigscheme.NewSchemeAndCodecs()
if err != nil {
return err
}
if err := scheme.Convert(in.ComponentConfigs.Kubelet, out.KubeletConfiguration.BaseConfig, nil); err != nil {
if err := componentconfigs.Scheme.Convert(in.ComponentConfigs.Kubelet, out.KubeletConfiguration.BaseConfig, nil); err != nil {
return err
}
}

View File

@ -127,6 +127,8 @@ func SetDefaults_Etcd(obj *MasterConfiguration) {
// SetDefaults_ProxyConfiguration assigns default values for the Proxy
func SetDefaults_ProxyConfiguration(obj *MasterConfiguration) {
// IMPORTANT NOTE: If you're changing this code you should mirror it to cmd/kubeadm/app/componentconfig/defaults.go
// and cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion.go.
if obj.KubeProxy.Config == nil {
obj.KubeProxy.Config = &kubeproxyconfigv1alpha1.KubeProxyConfiguration{}
}
@ -173,6 +175,8 @@ func SetDefaults_NodeConfiguration(obj *NodeConfiguration) {
// SetDefaults_KubeletConfiguration assigns default values to kubelet
func SetDefaults_KubeletConfiguration(obj *MasterConfiguration) {
// IMPORTANT NOTE: If you're changing this code you should mirror it to cmd/kubeadm/app/componentconfig/defaults.go
// and cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion.go.
if obj.KubeletConfiguration.BaseConfig == nil {
obj.KubeletConfiguration.BaseConfig = &kubeletconfigv1beta1.KubeletConfiguration{}
}
@ -247,8 +251,8 @@ func SetDefaults_BootstrapTokens(obj *MasterConfiguration) {
obj.BootstrapTokens = []BootstrapToken{{}}
}
for _, bt := range obj.BootstrapTokens {
SetDefaults_BootstrapToken(&bt)
for i := range obj.BootstrapTokens {
SetDefaults_BootstrapToken(&obj.BootstrapTokens[i])
}
}

View File

@ -19,6 +19,7 @@ package v1alpha3
import (
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
kubeletconfigscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
@ -32,64 +33,80 @@ func Convert_v1alpha3_MasterConfiguration_To_kubeadm_MasterConfiguration(in *Mas
return err
}
// TODO: Remove this conversion code ASAP, as the ComponentConfig structs should not be in the external version of the kubeadm API, but be marshalled as
// different YAML documents
if in.KubeProxy.Config != nil {
if out.ComponentConfigs.KubeProxy == nil {
out.ComponentConfigs.KubeProxy = &kubeproxyconfig.KubeProxyConfiguration{}
}
if err := kubeproxyconfigscheme.Scheme.Convert(in.KubeProxy.Config, out.ComponentConfigs.KubeProxy, nil); err != nil {
return err
}
}
if in.KubeletConfiguration.BaseConfig != nil {
if out.ComponentConfigs.Kubelet == nil {
out.ComponentConfigs.Kubelet = &kubeletconfig.KubeletConfiguration{}
}
// TODO: This conversion code is here ONLY for fuzzing tests. When we remove the v1alpha2 API, we can remove this (unnecessary)
// code. Right now this defaulting code has to be kept in sync with the defaulting code in cmd/kubeadm/app/apis/kubeadm/v1alpha2 and cmd/kubeadm/app/componentconfig
if out.ComponentConfigs.Kubelet == nil {
// Set the Kubelet ComponentConfig to an empty, defaulted struct
out.ComponentConfigs.Kubelet = &kubeletconfig.KubeletConfiguration{}
extkubeletconfig := &kubeletconfigv1beta1.KubeletConfiguration{}
scheme, _, err := kubeletconfigscheme.NewSchemeAndCodecs()
if err != nil {
return err
}
if err := scheme.Convert(in.KubeletConfiguration.BaseConfig, out.ComponentConfigs.Kubelet, nil); err != nil {
return err
}
scheme.Default(extkubeletconfig)
scheme.Convert(extkubeletconfig, out.ComponentConfigs.Kubelet, nil)
defaultKubeletConfiguration(in, out.ComponentConfigs.Kubelet)
}
if out.ComponentConfigs.KubeProxy == nil {
// Set the KubeProxy ComponentConfig to an empty, defaulted struct
out.ComponentConfigs.KubeProxy = &kubeproxyconfig.KubeProxyConfiguration{}
extkubeproxyconfig := &kubeproxyconfigv1alpha1.KubeProxyConfiguration{}
kubeproxyconfigscheme.Scheme.Default(extkubeproxyconfig)
kubeproxyconfigscheme.Scheme.Convert(extkubeproxyconfig, out.ComponentConfigs.KubeProxy, nil)
defaultKubeProxyConfiguration(in, out.ComponentConfigs.KubeProxy)
}
return nil
}
func Convert_kubeadm_MasterConfiguration_To_v1alpha3_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error {
if err := autoConvert_kubeadm_MasterConfiguration_To_v1alpha3_MasterConfiguration(in, out, s); err != nil {
return err
func defaultKubeProxyConfiguration(internalcfg *MasterConfiguration, obj *kubeproxyconfig.KubeProxyConfiguration) {
// NOTE: This code should be mirrored from cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go and cmd/kubeadm/app/componentconfig/defaults.go
if obj.ClusterCIDR == "" && internalcfg.Networking.PodSubnet != "" {
obj.ClusterCIDR = internalcfg.Networking.PodSubnet
}
// TODO: Remove this conversion code ASAP, as the ComponentConfig structs should not be in the external version of the kubeadm API, but be marshalled as
// different YAML documents
if in.ComponentConfigs.KubeProxy != nil {
if out.KubeProxy.Config == nil {
out.KubeProxy.Config = &kubeproxyconfigv1alpha1.KubeProxyConfiguration{}
}
if err := kubeproxyconfigscheme.Scheme.Convert(in.ComponentConfigs.KubeProxy, out.KubeProxy.Config, nil); err != nil {
return err
}
if obj.ClientConnection.KubeConfigFile == "" {
obj.ClientConnection.KubeConfigFile = "/var/lib/kube-proxy/kubeconfig.conf"
}
if in.ComponentConfigs.Kubelet != nil {
if out.KubeletConfiguration.BaseConfig == nil {
out.KubeletConfiguration.BaseConfig = &kubeletconfigv1beta1.KubeletConfiguration{}
}
}
scheme, _, err := kubeletconfigscheme.NewSchemeAndCodecs()
func defaultKubeletConfiguration(internalcfg *MasterConfiguration, obj *kubeletconfig.KubeletConfiguration) {
// NOTE: This code should be mirrored from cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go and cmd/kubeadm/app/componentconfig/defaults.go
if obj.StaticPodPath == "" {
obj.StaticPodPath = DefaultManifestsDir
}
if obj.ClusterDNS == nil {
dnsIP, err := constants.GetDNSIP(internalcfg.Networking.ServiceSubnet)
if err != nil {
return err
}
if err := scheme.Convert(in.ComponentConfigs.Kubelet, out.KubeletConfiguration.BaseConfig, nil); err != nil {
return err
obj.ClusterDNS = []string{DefaultClusterDNSIP}
} else {
obj.ClusterDNS = []string{dnsIP.String()}
}
}
return nil
if obj.ClusterDomain == "" {
obj.ClusterDomain = internalcfg.Networking.DNSDomain
}
// Enforce security-related kubelet options
// Require all clients to the kubelet API to have client certs signed by the cluster CA
obj.Authentication.X509.ClientCAFile = DefaultCACertPath
obj.Authentication.Anonymous.Enabled = false
// On every client request to the kubelet API, execute a webhook (SubjectAccessReview request) to the API server
// and ask it whether the client is authorized to access the kubelet API
obj.Authorization.Mode = kubeletconfig.KubeletAuthorizationModeWebhook
// Let clients using other authentication methods like ServiceAccount tokens also access the kubelet API
obj.Authentication.Webhook.Enabled = true
// Disable the readonly port of the kubelet, in order to not expose unnecessary information
obj.ReadOnlyPort = 0
// Enables client certificate rotation for the kubelet
obj.RotateCertificates = true
// Serve a /healthz webserver on localhost:10248 that kubeadm can talk to
obj.HealthzBindAddress = "127.0.0.1"
obj.HealthzPort = 10248
}

View File

@ -23,11 +23,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
kubeproxyscheme "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/scheme"
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
)
const (
@ -58,9 +53,6 @@ const (
DefaultProxyBindAddressv4 = "0.0.0.0"
// DefaultProxyBindAddressv6 is the default bind address when the advertise address is v6
DefaultProxyBindAddressv6 = "::"
// KubeproxyKubeConfigFileName defines the file name for the kube-proxy's KubeConfig file
KubeproxyKubeConfigFileName = "/var/lib/kube-proxy/kubeconfig.conf"
// DefaultDiscoveryTimeout specifies the default discovery timeout for kubeadm (used unless one is specified in the NodeConfiguration)
DefaultDiscoveryTimeout = 5 * time.Minute
)
@ -107,9 +99,7 @@ func SetDefaults_MasterConfiguration(obj *MasterConfiguration) {
SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration)
SetDefaults_BootstrapTokens(obj)
SetDefaults_KubeletConfiguration(obj)
SetDefaults_Etcd(obj)
SetDefaults_ProxyConfiguration(obj)
SetDefaults_AuditPolicyConfiguration(obj)
}
@ -125,22 +115,6 @@ func SetDefaults_Etcd(obj *MasterConfiguration) {
}
}
// SetDefaults_ProxyConfiguration assigns default values for the Proxy
func SetDefaults_ProxyConfiguration(obj *MasterConfiguration) {
if obj.KubeProxy.Config == nil {
obj.KubeProxy.Config = &kubeproxyconfigv1alpha1.KubeProxyConfiguration{}
}
if obj.KubeProxy.Config.ClusterCIDR == "" && obj.Networking.PodSubnet != "" {
obj.KubeProxy.Config.ClusterCIDR = obj.Networking.PodSubnet
}
if obj.KubeProxy.Config.ClientConnection.KubeConfigFile == "" {
obj.KubeProxy.Config.ClientConnection.KubeConfigFile = KubeproxyKubeConfigFileName
}
kubeproxyscheme.Scheme.Default(obj.KubeProxy.Config)
}
// SetDefaults_NodeConfiguration assigns default values to a regular node
func SetDefaults_NodeConfiguration(obj *NodeConfiguration) {
if obj.CACertPath == "" {
@ -171,55 +145,6 @@ func SetDefaults_NodeConfiguration(obj *NodeConfiguration) {
SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration)
}
// SetDefaults_KubeletConfiguration assigns default values to kubelet
func SetDefaults_KubeletConfiguration(obj *MasterConfiguration) {
if obj.KubeletConfiguration.BaseConfig == nil {
obj.KubeletConfiguration.BaseConfig = &kubeletconfigv1beta1.KubeletConfiguration{}
}
if obj.KubeletConfiguration.BaseConfig.StaticPodPath == "" {
obj.KubeletConfiguration.BaseConfig.StaticPodPath = DefaultManifestsDir
}
if obj.KubeletConfiguration.BaseConfig.ClusterDNS == nil {
dnsIP, err := constants.GetDNSIP(obj.Networking.ServiceSubnet)
if err != nil {
obj.KubeletConfiguration.BaseConfig.ClusterDNS = []string{DefaultClusterDNSIP}
} else {
obj.KubeletConfiguration.BaseConfig.ClusterDNS = []string{dnsIP.String()}
}
}
if obj.KubeletConfiguration.BaseConfig.ClusterDomain == "" {
obj.KubeletConfiguration.BaseConfig.ClusterDomain = obj.Networking.DNSDomain
}
// Enforce security-related kubelet options
// Require all clients to the kubelet API to have client certs signed by the cluster CA
obj.KubeletConfiguration.BaseConfig.Authentication.X509.ClientCAFile = DefaultCACertPath
obj.KubeletConfiguration.BaseConfig.Authentication.Anonymous.Enabled = utilpointer.BoolPtr(false)
// On every client request to the kubelet API, execute a webhook (SubjectAccessReview request) to the API server
// and ask it whether the client is authorized to access the kubelet API
obj.KubeletConfiguration.BaseConfig.Authorization.Mode = kubeletconfigv1beta1.KubeletAuthorizationModeWebhook
// Let clients using other authentication methods like ServiceAccount tokens also access the kubelet API
obj.KubeletConfiguration.BaseConfig.Authentication.Webhook.Enabled = utilpointer.BoolPtr(true)
// Disable the readonly port of the kubelet, in order to not expose unnecessary information
obj.KubeletConfiguration.BaseConfig.ReadOnlyPort = 0
// Enables client certificate rotation for the kubelet
obj.KubeletConfiguration.BaseConfig.RotateCertificates = true
// Serve a /healthz webserver on localhost:10248 that kubeadm can talk to
obj.KubeletConfiguration.BaseConfig.HealthzBindAddress = "127.0.0.1"
obj.KubeletConfiguration.BaseConfig.HealthzPort = utilpointer.Int32Ptr(10248)
scheme, _, _ := kubeletscheme.NewSchemeAndCodecs()
if scheme != nil {
scheme.Default(obj.KubeletConfiguration.BaseConfig)
}
}
func SetDefaults_NodeRegistrationOptions(obj *NodeRegistrationOptions) {
if obj.CRISocket == "" {
obj.CRISocket = DefaultCRISocket
@ -247,8 +172,8 @@ func SetDefaults_BootstrapTokens(obj *MasterConfiguration) {
obj.BootstrapTokens = []BootstrapToken{{}}
}
for _, bt := range obj.BootstrapTokens {
SetDefaults_BootstrapToken(&bt)
for i := range obj.BootstrapTokens {
SetDefaults_BootstrapToken(&obj.BootstrapTokens[i])
}
}

View File

@ -19,8 +19,6 @@ package v1alpha3
import (
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@ -47,12 +45,8 @@ type MasterConfiguration struct {
// API holds configuration for the k8s apiserver.
API API `json:"api"`
// KubeProxy holds configuration for the k8s service proxy.
KubeProxy KubeProxy `json:"kubeProxy"`
// Etcd holds configuration for etcd.
Etcd Etcd `json:"etcd"`
// KubeletConfiguration holds configuration for the kubelet.
KubeletConfiguration KubeletConfiguration `json:"kubeletConfiguration"`
// Networking holds configuration for the networking topology of the cluster.
Networking Networking `json:"networking"`
@ -281,11 +275,6 @@ type NodeConfiguration struct {
FeatureGates map[string]bool `json:"featureGates,omitempty"`
}
// KubeletConfiguration contains elements describing initial remote configuration of kubelet.
type KubeletConfiguration struct {
BaseConfig *kubeletconfigv1beta1.KubeletConfiguration `json:"baseConfig,omitempty"`
}
// HostPathMount contains elements describing volumes that are mounted from the
// host.
type HostPathMount struct {
@ -302,11 +291,6 @@ type HostPathMount struct {
PathType v1.HostPathType `json:"pathType,omitempty"`
}
// KubeProxy contains elements describing the proxy configuration.
type KubeProxy struct {
Config *kubeproxyconfigv1alpha1.KubeProxyConfiguration `json:"config,omitempty"`
}
// AuditPolicyConfiguration holds the options for configuring the api server audit policy.
type AuditPolicyConfiguration struct {
// Path is the local path to an audit policy.

View File

@ -32,14 +32,11 @@ import (
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
kubeletvalidation "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation"
"k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig"
proxyvalidation "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation"
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
)
@ -54,20 +51,10 @@ func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList
allErrs = append(allErrs, ValidateFeatureGates(c.FeatureGates, field.NewPath("featureGates"))...)
allErrs = append(allErrs, ValidateAPIEndpoint(&c.API, field.NewPath("api"))...)
allErrs = append(allErrs, ValidateEtcd(&c.Etcd, field.NewPath("etcd"))...)
// Validate other ComponentConfigs
allErrs = append(allErrs, ValidateProxy(c.ComponentConfigs.KubeProxy, field.NewPath("componentConfigs").Child("kubeProxy"))...)
allErrs = append(allErrs, ValidateKubeletConfiguration(c.ComponentConfigs.Kubelet, field.NewPath("componentConfigs").Child("kubelet"))...)
allErrs = append(allErrs, componentconfigs.Known.Validate(c)...)
return allErrs
}
// ValidateProxy validates proxy configuration and collects all encountered errors
func ValidateProxy(kubeProxyConfig *kubeproxyconfig.KubeProxyConfiguration, fldPath *field.Path) field.ErrorList {
if kubeProxyConfig == nil {
return field.ErrorList{}
}
return proxyvalidation.Validate(kubeProxyConfig)
}
// ValidateNodeConfiguration validates node configuration and collects all encountered errors
func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList {
allErrs := field.ErrorList{}
@ -420,15 +407,3 @@ func ValidateIgnorePreflightErrors(ignorePreflightErrors []string, skipPreflight
return ignoreErrors, allErrs.ToAggregate()
}
// ValidateKubeletConfiguration validates kubelet configuration and collects all encountered errors
func ValidateKubeletConfiguration(kubeletConfig *kubeletconfig.KubeletConfiguration, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if kubeletConfig == nil {
return allErrs
}
if err := kubeletvalidation.ValidateKubeletConfiguration(kubeletConfig); err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, "", err.Error()))
}
return allErrs
}