From f96ada0c04241c523923615fbdd5a650b5ac5bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Sun, 8 Jul 2018 21:27:53 +0300 Subject: [PATCH 1/6] Add a new package for handling all ComponentConfig-related code --- cmd/kubeadm/app/componentconfigs/defaults.go | 120 ++++++ .../app/componentconfigs/registrations.go | 148 ++++++++ cmd/kubeadm/app/componentconfigs/scheme.go | 41 ++ .../app/componentconfigs/validation.go | 46 +++ .../app/componentconfigs/validation_test.go | 351 ++++++++++++++++++ 5 files changed, 706 insertions(+) create mode 100644 cmd/kubeadm/app/componentconfigs/defaults.go create mode 100644 cmd/kubeadm/app/componentconfigs/registrations.go create mode 100644 cmd/kubeadm/app/componentconfigs/scheme.go create mode 100644 cmd/kubeadm/app/componentconfigs/validation.go create mode 100644 cmd/kubeadm/app/componentconfigs/validation_test.go diff --git a/cmd/kubeadm/app/componentconfigs/defaults.go b/cmd/kubeadm/app/componentconfigs/defaults.go new file mode 100644 index 00000000000..d9c5607e98b --- /dev/null +++ b/cmd/kubeadm/app/componentconfigs/defaults.go @@ -0,0 +1,120 @@ +/* +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 ( + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" + kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig" + kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" + utilpointer "k8s.io/kubernetes/pkg/util/pointer" +) + +const ( + // KubeproxyKubeConfigFileName defines the file name for the kube-proxy's KubeConfig file + KubeproxyKubeConfigFileName = "/var/lib/kube-proxy/kubeconfig.conf" +) + +// DefaultKubeProxyConfiguration assigns default values for the kube-proxy ComponentConfig +func DefaultKubeProxyConfiguration(internalcfg *kubeadmapi.MasterConfiguration) { + // IMPORTANT NOTE: If you're changing this code you should mirror it to cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go + // and cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion.go. TODO: Remove this requirement when v1alpha2 is removed. + externalproxycfg := &kubeproxyconfigv1alpha1.KubeProxyConfiguration{} + + // Do a roundtrip to the external version for defaulting + Scheme.Convert(internalcfg.ComponentConfigs.KubeProxy, externalproxycfg, nil) + + if externalproxycfg.ClusterCIDR == "" && internalcfg.Networking.PodSubnet != "" { + externalproxycfg.ClusterCIDR = internalcfg.Networking.PodSubnet + } + + if externalproxycfg.ClientConnection.KubeConfigFile == "" { + externalproxycfg.ClientConnection.KubeConfigFile = KubeproxyKubeConfigFileName + } + + // Run the rest of the kube-proxy defaulting code + kubeproxyconfigv1alpha1.SetDefaults_KubeProxyConfiguration(externalproxycfg) + + if internalcfg.ComponentConfigs.KubeProxy == nil { + internalcfg.ComponentConfigs.KubeProxy = &kubeproxyconfig.KubeProxyConfiguration{} + } + + // TODO: Figure out how to handle errors in defaulting code + // Go back to the internal version + Scheme.Convert(externalproxycfg, internalcfg.ComponentConfigs.KubeProxy, nil) +} + +// DefaultKubeletConfiguration assigns default values for the kubelet ComponentConfig +func DefaultKubeletConfiguration(internalcfg *kubeadmapi.MasterConfiguration) { + // IMPORTANT NOTE: If you're changing this code you should mirror it to cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go + // and cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion.go. TODO: Remove this requirement when v1alpha2 is removed. + externalkubeletcfg := &kubeletconfigv1beta1.KubeletConfiguration{} + + // Do a roundtrip to the external version for defaulting + Scheme.Convert(internalcfg.ComponentConfigs.Kubelet, externalkubeletcfg, nil) + + if externalkubeletcfg.StaticPodPath == "" { + externalkubeletcfg.StaticPodPath = kubeadmapiv1alpha3.DefaultManifestsDir + } + if externalkubeletcfg.ClusterDNS == nil { + dnsIP, err := constants.GetDNSIP(internalcfg.Networking.ServiceSubnet) + if err != nil { + externalkubeletcfg.ClusterDNS = []string{kubeadmapiv1alpha3.DefaultClusterDNSIP} + } else { + externalkubeletcfg.ClusterDNS = []string{dnsIP.String()} + } + } + if externalkubeletcfg.ClusterDomain == "" { + externalkubeletcfg.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 + externalkubeletcfg.Authentication.X509.ClientCAFile = kubeadmapiv1alpha3.DefaultCACertPath + externalkubeletcfg.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 + externalkubeletcfg.Authorization.Mode = kubeletconfigv1beta1.KubeletAuthorizationModeWebhook + + // Let clients using other authentication methods like ServiceAccount tokens also access the kubelet API + externalkubeletcfg.Authentication.Webhook.Enabled = utilpointer.BoolPtr(true) + + // Disable the readonly port of the kubelet, in order to not expose unnecessary information + externalkubeletcfg.ReadOnlyPort = 0 + + // Enables client certificate rotation for the kubelet + externalkubeletcfg.RotateCertificates = true + + // Serve a /healthz webserver on localhost:10248 that kubeadm can talk to + externalkubeletcfg.HealthzBindAddress = "127.0.0.1" + externalkubeletcfg.HealthzPort = utilpointer.Int32Ptr(10248) + + kubeletconfigv1beta1.SetDefaults_KubeletConfiguration(externalkubeletcfg) + + if internalcfg.ComponentConfigs.Kubelet == nil { + internalcfg.ComponentConfigs.Kubelet = &kubeletconfig.KubeletConfiguration{} + } + + // TODO: Figure out how to handle errors in defaulting code + // Go back to the internal version + Scheme.Convert(externalkubeletcfg, internalcfg.ComponentConfigs.Kubelet, nil) +} diff --git a/cmd/kubeadm/app/componentconfigs/registrations.go b/cmd/kubeadm/app/componentconfigs/registrations.go new file mode 100644 index 00000000000..994b12020a0 --- /dev/null +++ b/cmd/kubeadm/app/componentconfigs/registrations.go @@ -0,0 +1,148 @@ +/* +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" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" + kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig" + kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/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.MasterConfiguration) + // ValidateFunc is a function that should validate the ComponentConfig type embedded in the internal kubeadm config struct + ValidateFunc func(*kubeadmapi.MasterConfiguration, *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.MasterConfiguration) (runtime.Object, bool) + // SetToInternalConfig sets the pointer to a ComponentConfig API object embedded in the internal kubeadm config struct + SetToInternalConfig func(runtime.Object, *kubeadmapi.MasterConfiguration) bool +} + +// 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 + // object, using the componentconfig Codecs that knows about all APIs + if err := runtime.DecodeInto(Codecs.UniversalDecoder(), fileContent, obj); err != nil { + return nil, err + } + return obj, 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: []AddToSchemeFunc{kubeproxyconfig.AddToScheme, kubeproxyconfigv1alpha1.AddToScheme}, + DefaulterFunc: DefaultKubeProxyConfiguration, + ValidateFunc: ValidateKubeProxyConfiguration, + EmptyValue: &kubeproxyconfig.KubeProxyConfiguration{}, + GetFromInternalConfig: func(cfg *kubeadmapi.MasterConfiguration) (runtime.Object, bool) { + return cfg.ComponentConfigs.KubeProxy, cfg.ComponentConfigs.KubeProxy != nil + }, + SetToInternalConfig: func(obj runtime.Object, cfg *kubeadmapi.MasterConfiguration) bool { + kubeproxyConfig, ok := obj.(*kubeproxyconfig.KubeProxyConfiguration) + if ok { + cfg.ComponentConfigs.KubeProxy = kubeproxyConfig + } + return ok + }, + }, + KubeletConfigurationKind: { + MarshalGroupVersion: kubeletconfigv1beta1.SchemeGroupVersion, + AddToSchemeFuncs: []AddToSchemeFunc{kubeletconfig.AddToScheme, kubeletconfigv1beta1.AddToScheme}, + DefaulterFunc: DefaultKubeletConfiguration, + ValidateFunc: ValidateKubeletConfiguration, + EmptyValue: &kubeletconfig.KubeletConfiguration{}, + GetFromInternalConfig: func(cfg *kubeadmapi.MasterConfiguration) (runtime.Object, bool) { + return cfg.ComponentConfigs.Kubelet, cfg.ComponentConfigs.Kubelet != nil + }, + SetToInternalConfig: func(obj runtime.Object, cfg *kubeadmapi.MasterConfiguration) bool { + kubeletConfig, ok := obj.(*kubeletconfig.KubeletConfiguration) + if ok { + cfg.ComponentConfigs.Kubelet = kubeletConfig + } + return ok + }, + }, +} + +// 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.MasterConfiguration) { + for _, registration := range *rs { + registration.DefaulterFunc(internalcfg) + } +} + +// Validate validates the ComponentConfig parts of the internal kubeadm API type +func (rs *Registrations) Validate(internalcfg *kubeadmapi.MasterConfiguration) field.ErrorList { + allErrs := field.ErrorList{} + for kind, registration := range *rs { + allErrs = append(allErrs, registration.ValidateFunc(internalcfg, field.NewPath(string(kind)))...) + } + return allErrs +} diff --git a/cmd/kubeadm/app/componentconfigs/scheme.go b/cmd/kubeadm/app/componentconfigs/scheme.go new file mode 100644 index 00000000000..edb545416c8 --- /dev/null +++ b/cmd/kubeadm/app/componentconfigs/scheme.go @@ -0,0 +1,41 @@ +/* +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 ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +// Scheme is the runtime.Scheme to which all supported kubeadm ComponentConfig API types are registered. +var Scheme = runtime.NewScheme() + +// Codecs provides access to encoding and decoding for the scheme. +var Codecs = serializer.NewCodecFactory(Scheme) + +func init() { + metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + AddToScheme(Scheme) +} + +// AddToScheme builds the kubeadm ComponentConfig scheme using all known ComponentConfig versions. +func AddToScheme(scheme *runtime.Scheme) { + utilruntime.Must(Known.AddToScheme(scheme)) +} diff --git a/cmd/kubeadm/app/componentconfigs/validation.go b/cmd/kubeadm/app/componentconfigs/validation.go new file mode 100644 index 00000000000..d15f6f8b9ec --- /dev/null +++ b/cmd/kubeadm/app/componentconfigs/validation.go @@ -0,0 +1,46 @@ +/* +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/util/validation/field" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeletvalidation "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation" + proxyvalidation "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation" +) + +// ValidateKubeProxyConfiguration validates proxy configuration and collects all encountered errors +func ValidateKubeProxyConfiguration(internalcfg *kubeadmapi.MasterConfiguration, _ *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if internalcfg.ComponentConfigs.KubeProxy == nil { + return allErrs + } + return proxyvalidation.Validate(internalcfg.ComponentConfigs.KubeProxy) +} + +// ValidateKubeletConfiguration validates kubelet configuration and collects all encountered errors +func ValidateKubeletConfiguration(internalcfg *kubeadmapi.MasterConfiguration, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if internalcfg.ComponentConfigs.Kubelet == nil { + return allErrs + } + + if err := kubeletvalidation.ValidateKubeletConfiguration(internalcfg.ComponentConfigs.Kubelet); err != nil { + allErrs = append(allErrs, field.Invalid(fldPath, "", err.Error())) + } + return allErrs +} diff --git a/cmd/kubeadm/app/componentconfigs/validation_test.go b/cmd/kubeadm/app/componentconfigs/validation_test.go new file mode 100644 index 00000000000..8e76614f4e4 --- /dev/null +++ b/cmd/kubeadm/app/componentconfigs/validation_test.go @@ -0,0 +1,351 @@ +/* +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 ( + "strings" + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" + "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig" + utilpointer "k8s.io/kubernetes/pkg/util/pointer" +) + +func TestValidateKubeProxyConfiguration(t *testing.T) { + var tests = []struct { + masterConfig *kubeadm.MasterConfiguration + msg string + expectErr bool + }{ + { + masterConfig: &kubeadm.MasterConfiguration{ + ComponentConfigs: kubeadm.ComponentConfigs{ + KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ + BindAddress: "192.168.59.103", + HealthzBindAddress: "0.0.0.0:10256", + MetricsBindAddress: "127.0.0.1:10249", + ClusterCIDR: "192.168.59.0/24", + UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, + ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, + IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ + MasqueradeAll: true, + SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, + }, + IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ + SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + }, + Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ + Max: utilpointer.Int32Ptr(2), + MaxPerCore: utilpointer.Int32Ptr(1), + Min: utilpointer.Int32Ptr(1), + TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, + TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, + }, + }, + }, + }, + expectErr: false, + }, + { + masterConfig: &kubeadm.MasterConfiguration{ + ComponentConfigs: kubeadm.ComponentConfigs{ + KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ + // only BindAddress is invalid + BindAddress: "10.10.12.11:2000", + HealthzBindAddress: "0.0.0.0:10256", + MetricsBindAddress: "127.0.0.1:10249", + ClusterCIDR: "192.168.59.0/24", + UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, + ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, + IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ + MasqueradeAll: true, + SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, + }, + IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ + SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + }, + Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ + Max: utilpointer.Int32Ptr(2), + MaxPerCore: utilpointer.Int32Ptr(1), + Min: utilpointer.Int32Ptr(1), + TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, + TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, + }, + }, + }, + }, + msg: "not a valid textual representation of an IP address", + expectErr: true, + }, + { + masterConfig: &kubeadm.MasterConfiguration{ + ComponentConfigs: kubeadm.ComponentConfigs{ + KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ + BindAddress: "10.10.12.11", + // only HealthzBindAddress is invalid + HealthzBindAddress: "0.0.0.0", + MetricsBindAddress: "127.0.0.1:10249", + ClusterCIDR: "192.168.59.0/24", + UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, + ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, + IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ + MasqueradeAll: true, + SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, + }, + IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ + SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + }, + Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ + Max: utilpointer.Int32Ptr(2), + MaxPerCore: utilpointer.Int32Ptr(1), + Min: utilpointer.Int32Ptr(1), + TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, + TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, + }, + }, + }, + }, + msg: "must be IP:port", + expectErr: true, + }, + { + masterConfig: &kubeadm.MasterConfiguration{ + ComponentConfigs: kubeadm.ComponentConfigs{ + KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ + BindAddress: "10.10.12.11", + HealthzBindAddress: "0.0.0.0:12345", + // only MetricsBindAddress is invalid + MetricsBindAddress: "127.0.0.1", + ClusterCIDR: "192.168.59.0/24", + UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, + ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, + IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ + MasqueradeAll: true, + SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, + }, + IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ + SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + }, + Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ + Max: utilpointer.Int32Ptr(2), + MaxPerCore: utilpointer.Int32Ptr(1), + Min: utilpointer.Int32Ptr(1), + TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, + TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, + }, + }, + }, + }, + msg: "must be IP:port", + expectErr: true, + }, + { + masterConfig: &kubeadm.MasterConfiguration{ + ComponentConfigs: kubeadm.ComponentConfigs{ + KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ + BindAddress: "10.10.12.11", + HealthzBindAddress: "0.0.0.0:12345", + MetricsBindAddress: "127.0.0.1:10249", + // only ClusterCIDR is invalid + ClusterCIDR: "192.168.59.0", + UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, + ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, + IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ + MasqueradeAll: true, + SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, + }, + IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ + SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + }, + Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ + Max: utilpointer.Int32Ptr(2), + MaxPerCore: utilpointer.Int32Ptr(1), + Min: utilpointer.Int32Ptr(1), + TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, + TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, + }, + }, + }, + }, + msg: "must be a valid CIDR block (e.g. 10.100.0.0/16)", + expectErr: true, + }, + { + masterConfig: &kubeadm.MasterConfiguration{ + ComponentConfigs: kubeadm.ComponentConfigs{ + KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ + BindAddress: "10.10.12.11", + HealthzBindAddress: "0.0.0.0:12345", + MetricsBindAddress: "127.0.0.1:10249", + ClusterCIDR: "192.168.59.0/24", + // only UDPIdleTimeout is invalid + UDPIdleTimeout: metav1.Duration{Duration: -1 * time.Second}, + ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, + IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ + MasqueradeAll: true, + SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, + }, + IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ + SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + }, + Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ + Max: utilpointer.Int32Ptr(2), + MaxPerCore: utilpointer.Int32Ptr(1), + Min: utilpointer.Int32Ptr(1), + TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, + TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, + }, + }, + }, + }, + msg: "must be greater than 0", + expectErr: true, + }, + { + masterConfig: &kubeadm.MasterConfiguration{ + ComponentConfigs: kubeadm.ComponentConfigs{ + KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ + BindAddress: "10.10.12.11", + HealthzBindAddress: "0.0.0.0:12345", + MetricsBindAddress: "127.0.0.1:10249", + ClusterCIDR: "192.168.59.0/24", + UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, + // only ConfigSyncPeriod is invalid + ConfigSyncPeriod: metav1.Duration{Duration: -1 * time.Second}, + IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ + MasqueradeAll: true, + SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, + }, + IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ + SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, + MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, + }, + Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ + Max: utilpointer.Int32Ptr(2), + MaxPerCore: utilpointer.Int32Ptr(1), + Min: utilpointer.Int32Ptr(1), + TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, + TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, + }, + }, + }, + }, + msg: "must be greater than 0", + expectErr: true, + }, + } + for i, rt := range tests { + err := ValidateKubeProxyConfiguration(rt.masterConfig, nil).ToAggregate() + if (err != nil) != rt.expectErr { + t.Errorf("%d failed ValidateKubeProxyConfiguration: expected error %t, got error %t", i, rt.expectErr, err != nil) + } + if err != nil && !strings.Contains(err.Error(), rt.msg) { + t.Errorf("%d failed ValidateKubeProxyConfiguration: unexpected error: %v, expected: %s", i, err, rt.msg) + } + } +} + +func TestValidateKubeletConfiguration(t *testing.T) { + var tests = []struct { + masterConfig *kubeadm.MasterConfiguration + expectErr bool + }{ + { + masterConfig: &kubeadm.MasterConfiguration{ + ComponentConfigs: kubeadm.ComponentConfigs{ + Kubelet: &kubeletconfig.KubeletConfiguration{ + CgroupsPerQOS: true, + EnforceNodeAllocatable: []string{"pods", "system-reserved", "kube-reserved"}, + SystemCgroups: "", + CgroupRoot: "", + EventBurst: 10, + EventRecordQPS: 5, + HealthzPort: 10248, + ImageGCHighThresholdPercent: 85, + ImageGCLowThresholdPercent: 80, + IPTablesDropBit: 15, + IPTablesMasqueradeBit: 14, + KubeAPIBurst: 10, + KubeAPIQPS: 5, + MaxOpenFiles: 1000000, + MaxPods: 110, + OOMScoreAdj: -999, + PodsPerCore: 100, + Port: 65535, + ReadOnlyPort: 0, + RegistryBurst: 10, + RegistryPullQPS: 5, + HairpinMode: "promiscuous-bridge", + }, + }, + }, + expectErr: false, + }, + { + masterConfig: &kubeadm.MasterConfiguration{ + ComponentConfigs: kubeadm.ComponentConfigs{ + Kubelet: &kubeletconfig.KubeletConfiguration{ + CgroupsPerQOS: false, + EnforceNodeAllocatable: []string{"pods", "system-reserved", "kube-reserved", "illegal-key"}, + SystemCgroups: "/", + CgroupRoot: "", + EventBurst: -10, + EventRecordQPS: -10, + HealthzPort: -10, + ImageGCHighThresholdPercent: 101, + ImageGCLowThresholdPercent: 101, + IPTablesDropBit: -10, + IPTablesMasqueradeBit: -10, + KubeAPIBurst: -10, + KubeAPIQPS: -10, + MaxOpenFiles: -10, + MaxPods: -10, + OOMScoreAdj: -1001, + PodsPerCore: -10, + Port: 0, + ReadOnlyPort: -10, + RegistryBurst: -10, + RegistryPullQPS: -10, + }, + }, + }, + expectErr: true, + }, + } + for i, rt := range tests { + err := ValidateKubeletConfiguration(rt.masterConfig, nil).ToAggregate() + if (err != nil) != rt.expectErr { + t.Errorf("%d failed ValidateKubeletConfiguration: expected error %t, got error %t", i, rt.expectErr, err != nil) + } + } +} From 5aef95ebe1da5487db642270867cb60dd3f58267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Sun, 8 Jul 2018 21:31:35 +0300 Subject: [PATCH 2/6] Remove the ComponentConfig structs from the external v1alpha3 API. Use the new componentconfigs pkg for validation and conversion --- cmd/kubeadm/app/apis/kubeadm/types.go | 9 ++ .../app/apis/kubeadm/v1alpha2/conversion.go | 21 +--- .../app/apis/kubeadm/v1alpha2/defaults.go | 8 +- .../app/apis/kubeadm/v1alpha3/conversion.go | 103 ++++++++++-------- .../app/apis/kubeadm/v1alpha3/defaults.go | 79 +------------- .../app/apis/kubeadm/v1alpha3/types.go | 16 --- .../app/apis/kubeadm/validation/validation.go | 29 +---- 7 files changed, 84 insertions(+), 181 deletions(-) diff --git a/cmd/kubeadm/app/apis/kubeadm/types.go b/cmd/kubeadm/app/apis/kubeadm/types.go index 234f7ab7f77..3eaa5a6c955 100644 --- a/cmd/kubeadm/app/apis/kubeadm/types.go +++ b/cmd/kubeadm/app/apis/kubeadm/types.go @@ -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. diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/conversion.go index 548f0aa318a..a406319a508 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/conversion.go @@ -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 } } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go index c9b8980bdcd..f513ee29a9e 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/defaults.go @@ -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]) } } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion.go index 16c59831c1a..1ebe2966908 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion.go @@ -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 } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults.go index a2c6d73423b..4711ddc024f 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults.go @@ -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]) } } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/types.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/types.go index fcb0f78005f..3504d384dda 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/types.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/types.go @@ -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. diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/validation.go b/cmd/kubeadm/app/apis/kubeadm/validation/validation.go index 23875e777f1..9d965af8688 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/validation.go +++ b/cmd/kubeadm/app/apis/kubeadm/validation/validation.go @@ -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 -} From 495ac9883d8b92906b26f1fe27e97ef167790cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Sun, 8 Jul 2018 21:32:28 +0300 Subject: [PATCH 3/6] Make kubeadm support {un,}marshalling ComponentConfig structs as different YAML documents --- cmd/kubeadm/app/cmd/config.go | 5 +- cmd/kubeadm/app/cmd/upgrade/common.go | 8 +- cmd/kubeadm/app/phases/addons/proxy/proxy.go | 5 +- cmd/kubeadm/app/phases/kubelet/config.go | 13 +- .../app/phases/uploadconfig/uploadconfig.go | 14 +- cmd/kubeadm/app/util/config/cluster.go | 1 + cmd/kubeadm/app/util/config/common.go | 11 ++ cmd/kubeadm/app/util/config/masterconfig.go | 137 +++++++++++++++++- 8 files changed, 165 insertions(+), 29 deletions(-) diff --git a/cmd/kubeadm/app/cmd/config.go b/cmd/kubeadm/app/cmd/config.go index 9f9f888f6eb..b477d70fbfd 100644 --- a/cmd/kubeadm/app/cmd/config.go +++ b/cmd/kubeadm/app/cmd/config.go @@ -89,6 +89,7 @@ func NewCmdConfig(out io.Writer) *cobra.Command { } // NewCmdConfigPrintDefault returns cobra.Command for "kubeadm config print-default" command +// TODO: Make it possible to print the defaults for the componentconfig API objects, and default to printing them out as well func NewCmdConfigPrintDefault(out io.Writer) *cobra.Command { apiObjects := []string{} cmd := &cobra.Command{ @@ -143,7 +144,7 @@ func getDefaultAPIObjectBytes(apiObject string) ([]byte, error) { if err != nil { return []byte{}, err } - return kubeadmutil.MarshalToYamlForCodecs(internalcfg, kubeadmapiv1alpha3.SchemeGroupVersion, kubeadmscheme.Codecs) + return configutil.MarshalKubeadmConfigObject(internalcfg) } // NewCmdConfigMigrate returns cobra.Command for "kubeadm config migrate" command @@ -175,7 +176,7 @@ func NewCmdConfigMigrate(out io.Writer) *cobra.Command { internalcfg, err := configutil.AnyConfigFileAndDefaultsToInternal(oldCfgPath) kubeadmutil.CheckErr(err) - outputBytes, err := kubeadmutil.MarshalToYamlForCodecs(internalcfg, kubeadmapiv1alpha3.SchemeGroupVersion, kubeadmscheme.Codecs) + outputBytes, err := configutil.MarshalKubeadmConfigObject(internalcfg) kubeadmutil.CheckErr(err) if newCfgPath == "" { diff --git a/cmd/kubeadm/app/cmd/upgrade/common.go b/cmd/kubeadm/app/cmd/upgrade/common.go index 2ef25a0a1a6..ec5ffbd7762 100644 --- a/cmd/kubeadm/app/cmd/upgrade/common.go +++ b/cmd/kubeadm/app/cmd/upgrade/common.go @@ -30,13 +30,10 @@ import ( fakediscovery "k8s.io/client-go/discovery/fake" clientset "k8s.io/client-go/kubernetes" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" - kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" "k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade" "k8s.io/kubernetes/cmd/kubeadm/app/preflight" - kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun" @@ -118,10 +115,7 @@ func printConfiguration(cfg *kubeadmapi.MasterConfiguration, w io.Writer) { return } - externalcfg := &kubeadmapiv1alpha3.MasterConfiguration{} - kubeadmscheme.Scheme.Convert(cfg, externalcfg, nil) - - cfgYaml, err := kubeadmutil.MarshalToYamlForCodecs(externalcfg, kubeadmapiv1alpha3.SchemeGroupVersion, kubeadmscheme.Codecs) + cfgYaml, err := configutil.MarshalKubeadmConfigObject(cfg) if err == nil { fmt.Fprintln(w, "[upgrade/config] Configuration used:") diff --git a/cmd/kubeadm/app/phases/addons/proxy/proxy.go b/cmd/kubeadm/app/phases/addons/proxy/proxy.go index fadb92d0764..0762aa7877b 100644 --- a/cmd/kubeadm/app/phases/addons/proxy/proxy.go +++ b/cmd/kubeadm/app/phases/addons/proxy/proxy.go @@ -29,11 +29,10 @@ import ( clientset "k8s.io/client-go/kubernetes" clientsetscheme "k8s.io/client-go/kubernetes/scheme" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" - kubeproxyconfigscheme "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/scheme" - kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" ) const ( @@ -57,7 +56,7 @@ func EnsureProxyAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Inte return err } - proxyBytes, err := kubeadmutil.MarshalToYamlForCodecs(cfg.ComponentConfigs.KubeProxy, kubeproxyconfigv1alpha1.SchemeGroupVersion, kubeproxyconfigscheme.Codecs) + proxyBytes, err := componentconfigs.Known[componentconfigs.KubeProxyConfigurationKind].Marshal(cfg.ComponentConfigs.KubeProxy) if err != nil { return fmt.Errorf("error when marshaling: %v", err) } diff --git a/cmd/kubeadm/app/phases/kubelet/config.go b/cmd/kubeadm/app/phases/kubelet/config.go index 724ae49005f..f927f4d2c5f 100644 --- a/cmd/kubeadm/app/phases/kubelet/config.go +++ b/cmd/kubeadm/app/phases/kubelet/config.go @@ -28,13 +28,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" rbachelper "k8s.io/kubernetes/pkg/apis/rbac/v1" "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/util/version" ) @@ -154,14 +152,9 @@ func configMapRBACName(k8sVersion *version.Version) string { return fmt.Sprintf("%s%d.%d", kubeadmconstants.KubeletBaseConfigMapRolePrefix, k8sVersion.Major(), k8sVersion.Minor()) } -// getConfigBytes marshals a kubeletconfiguration object to bytes +// getConfigBytes marshals a KubeletConfiguration object to bytes func getConfigBytes(kubeletConfig *kubeletconfig.KubeletConfiguration) ([]byte, error) { - _, kubeletCodecs, err := kubeletconfigscheme.NewSchemeAndCodecs() - if err != nil { - return []byte{}, err - } - - return kubeadmutil.MarshalToYamlForCodecs(kubeletConfig, kubeletconfigv1beta1.SchemeGroupVersion, *kubeletCodecs) + return componentconfigs.Known[componentconfigs.KubeletConfigurationKind].Marshal(kubeletConfig) } // writeConfigBytesToDisk writes a byte slice down to disk at the specific location of the kubelet config file diff --git a/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go b/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go index b68762e88e8..76752c2183b 100644 --- a/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go +++ b/cmd/kubeadm/app/phases/uploadconfig/uploadconfig.go @@ -23,11 +23,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" - kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" + configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" ) // UploadConfiguration saves the MasterConfiguration used for later reference (when upgrading for instance) @@ -41,9 +39,17 @@ func UploadConfiguration(cfg *kubeadmapi.MasterConfiguration, client clientset.I cfgToUpload.BootstrapTokens = nil // Clear the NodeRegistration object. cfgToUpload.NodeRegistration = kubeadmapi.NodeRegistrationOptions{} + // TODO: Reset the .ComponentConfig struct like this: + // cfgToUpload.ComponentConfigs = kubeadmapi.ComponentConfigs{} + // in order to not upload any other components' config to the kubeadm-config + // ConfigMap. The components store their config in their own ConfigMaps. + // Before this line can be uncommented util/config.loadConfigurationBytes() + // needs to support reading the different components' ConfigMaps first. + // Marshal the object into YAML - cfgYaml, err := kubeadmutil.MarshalToYamlForCodecs(cfgToUpload, kubeadmapiv1alpha3.SchemeGroupVersion, kubeadmscheme.Codecs) + cfgYaml, err := configutil.MarshalKubeadmConfigObject(cfgToUpload) if err != nil { + fmt.Println("err", err.Error()) return err } diff --git a/cmd/kubeadm/app/util/config/cluster.go b/cmd/kubeadm/app/util/config/cluster.go index f2ec1a777c9..369bba9610c 100644 --- a/cmd/kubeadm/app/util/config/cluster.go +++ b/cmd/kubeadm/app/util/config/cluster.go @@ -59,6 +59,7 @@ func loadConfigurationBytes(client clientset.Interface, w io.Writer, logPrefix, } else if err != nil { return []byte{}, fmt.Errorf("an unexpected error happened when trying to get the ConfigMap %q in the %s namespace: %v", constants.MasterConfigurationConfigMap, metav1.NamespaceSystem, err) } + // TODO: Load the kube-proxy and kubelet ComponentConfig ConfigMaps here as different YAML documents and append to the byte slice fmt.Fprintf(w, "[%s] FYI: You can look at this config file with 'kubectl -n %s get cm %s -oyaml'\n", logPrefix, metav1.NamespaceSystem, constants.MasterConfigurationConfigMap) return []byte(configMap.Data[constants.MasterConfigurationConfigMapKey]), nil diff --git a/cmd/kubeadm/app/util/config/common.go b/cmd/kubeadm/app/util/config/common.go index 6c0e20b7470..f1efb8f0301 100644 --- a/cmd/kubeadm/app/util/config/common.go +++ b/cmd/kubeadm/app/util/config/common.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3" "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" @@ -53,6 +54,16 @@ func AnyConfigFileAndDefaultsToInternal(cfgPath string) (runtime.Object, error) return nil, fmt.Errorf("didn't recognize types with GroupVersionKind: %v", gvks) } +// MarshalKubeadmConfigObject marshals an Object registered in the kubeadm scheme. If the object is a MasterConfiguration, some extra logic is run +func MarshalKubeadmConfigObject(obj runtime.Object) ([]byte, error) { + switch internalcfg := obj.(type) { + case *kubeadmapi.MasterConfiguration: + return MarshalMasterConfigurationToBytes(internalcfg, kubeadmapiv1alpha3.SchemeGroupVersion) + default: + return kubeadmutil.MarshalToYamlForCodecs(obj, kubeadmapiv1alpha3.SchemeGroupVersion, kubeadmscheme.Codecs) + } +} + // DetectUnsupportedVersion reads YAML bytes, extracts the TypeMeta information and errors out with an user-friendly message if the API spec is too old for this kubeadm version func DetectUnsupportedVersion(b []byte) error { gvks, err := kubeadmutil.GroupVersionKindsFromBytes(b) diff --git a/cmd/kubeadm/app/util/config/masterconfig.go b/cmd/kubeadm/app/util/config/masterconfig.go index c491e759f7a..a4092f12d25 100644 --- a/cmd/kubeadm/app/util/config/masterconfig.go +++ b/cmd/kubeadm/app/util/config/masterconfig.go @@ -17,27 +17,36 @@ limitations under the License. package config import ( + "bytes" "fmt" "io/ioutil" "net" + "reflect" + "sort" "github.com/golang/glog" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" netutil "k8s.io/apimachinery/pkg/util/net" bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" + "k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" nodeutil "k8s.io/kubernetes/pkg/util/node" ) // SetInitDynamicDefaults checks and sets configuration values for the MasterConfiguration object func SetInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error { + // Default all the embedded ComponentConfig structs + componentconfigs.Known.Default(cfg) + // validate cfg.API.AdvertiseAddress. addressIP := net.ParseIP(cfg.API.AdvertiseAddress) if addressIP == nil && cfg.API.AdvertiseAddress != "" { @@ -115,7 +124,7 @@ func ConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg * return BytesToInternalConfig(b) } - // Takes passed flags into account; the defaulting is executed once again enforcing assignement of + // Takes passed flags into account; the defaulting is executed once again enforcing assignment of // static default values to cfg only for values not provided with flags kubeadmscheme.Scheme.Default(defaultversionedcfg) kubeadmscheme.Scheme.Convert(defaultversionedcfg, internalcfg, nil) @@ -123,18 +132,65 @@ func ConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg * return defaultAndValidate(internalcfg) } -// BytesToInternalConfig converts a byte array to an internal, defaulted and validated configuration object +// BytesToInternalConfig converts a byte slice to an internal, defaulted and validated configuration object. +// The byte slice may contain one or many different YAML documents. These YAML documents are parsed one-by-one +// and well-known ComponentConfig GroupVersionKinds are stored inside of the internal MasterConfiguration struct func BytesToInternalConfig(b []byte) (*kubeadmapi.MasterConfiguration, error) { internalcfg := &kubeadmapi.MasterConfiguration{} + decodedObjs := map[componentconfigs.RegistrationKind]runtime.Object{} + masterConfigFound := false if err := DetectUnsupportedVersion(b); err != nil { return nil, err } - if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), b, internalcfg); err != nil { + gvkmap, err := kubeadmutil.SplitYAMLDocuments(b) + if err != nil { return nil, err } + for gvk, fileContent := range gvkmap { + // Try to get the registration for the ComponentConfig based on the kind + regKind := componentconfigs.RegistrationKind(gvk.Kind) + registration, found := componentconfigs.Known[regKind] + if found { + // Unmarshal the bytes from the YAML document into a runtime.Object containing the ComponentConfiguration struct + obj, err := registration.Unmarshal(fileContent) + if err != nil { + return nil, err + } + decodedObjs[regKind] = obj + continue + } + + if gvk.Kind == kubeadmconstants.MasterConfigurationKind { + if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), fileContent, internalcfg); err != nil { + return nil, err + } + masterConfigFound = true + continue + } + + fmt.Printf("[config] WARNING: Ignored YAML document with GroupVersionKind %v\n", gvk) + } + // Just as an extra safety check, don't proceed if a MasterConfiguration object wasn't found + if !masterConfigFound { + return nil, fmt.Errorf("no MasterConfiguration kind was found in the YAML file") + } + + // Save the loaded ComponentConfig objects in the internalcfg object + for kind, obj := range decodedObjs { + registration, found := componentconfigs.Known[kind] + if found { + if ok := registration.SetToInternalConfig(obj, internalcfg); !ok { + return nil, fmt.Errorf("couldn't save componentconfig value for kind %q", string(kind)) + } + } else { + // This should never happen in practice + fmt.Printf("[config] WARNING: Decoded a kind that couldn't be saved to the internal configuration: %q\n", string(kind)) + } + } + return defaultAndValidate(internalcfg) } @@ -147,5 +203,80 @@ func defaultAndValidate(cfg *kubeadmapi.MasterConfiguration) (*kubeadmapi.Master if err := validation.ValidateMasterConfiguration(cfg).ToAggregate(); err != nil { return nil, err } + return cfg, nil } + +func defaultedInternalConfig() *kubeadmapi.MasterConfiguration { + externalcfg := &kubeadmapiv1alpha3.MasterConfiguration{} + internalcfg := &kubeadmapi.MasterConfiguration{} + + kubeadmscheme.Scheme.Default(externalcfg) + kubeadmscheme.Scheme.Convert(externalcfg, internalcfg, nil) + + // Default the embedded ComponentConfig structs + componentconfigs.Known.Default(internalcfg) + return internalcfg +} + +// MarshalMasterConfigurationToBytes marshals the internal MasterConfiguration object to bytes. It writes the embedded +// ComponentConfiguration objects out as separate YAML documents +func MarshalMasterConfigurationToBytes(cfg *kubeadmapi.MasterConfiguration, gv schema.GroupVersion) ([]byte, error) { + masterbytes, err := kubeadmutil.MarshalToYamlForCodecs(cfg, gv, kubeadmscheme.Codecs) + if err != nil { + return []byte{}, err + } + allFiles := [][]byte{masterbytes} + componentConfigContent := map[string][]byte{} + + // If the specified groupversion is targeting the internal type, don't print the extra componentconfig YAML documents + if gv.Version != runtime.APIVersionInternal { + + defaultedcfg := defaultedInternalConfig() + + for kind, registration := range componentconfigs.Known { + // If the ComponentConfig struct for the current registration is nil, skip it when marshalling + realobj, ok := registration.GetFromInternalConfig(cfg) + if !ok { + continue + } + + defaultedobj, ok := registration.GetFromInternalConfig(defaultedcfg) + // Invalid: The caller asked to not print the componentconfigs if defaulted, but defaultComponentConfigs() wasn't able to create default objects to use for reference + if !ok { + return []byte{}, fmt.Errorf("couldn't create a default componentconfig object") + } + + // If the real ComponentConfig object differs from the default, print it out. If not, there's no need to print it out, so skip it + if !reflect.DeepEqual(realobj, defaultedobj) { + contentBytes, err := registration.Marshal(realobj) + if err != nil { + return []byte{}, err + } + componentConfigContent[string(kind)] = contentBytes + } + } + } + + // Sort the ComponentConfig files by kind when marshalling + sortedComponentConfigFiles := consistentOrderByteSlice(componentConfigContent) + allFiles = append(allFiles, sortedComponentConfigFiles...) + return bytes.Join(allFiles, []byte(kubeadmconstants.YAMLDocumentSeparator)), nil +} + +// consistentOrderByteSlice takes a map of a string key and a byte slice, and returns a byte slice of byte slices +// with consistent ordering, where the keys in the map determine the ordering of the return value. This has to be +// done as the order of a for...range loop over a map in go is undeterministic, and could otherwise lead to flakes +// in e.g. unit tests when marshalling content with a random order +func consistentOrderByteSlice(content map[string][]byte) [][]byte { + keys := []string{} + sortedContent := [][]byte{} + for key := range content { + keys = append(keys, key) + } + sort.Strings(keys) + for _, key := range keys { + sortedContent = append(sortedContent, content[key]) + } + return sortedContent +} From 17b3b2819067805ad508b7e18f60cd53cabe062a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Sun, 8 Jul 2018 21:32:51 +0300 Subject: [PATCH 4/6] Update unit tests --- cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go | 77 +---- .../kubeadm/validation/validation_test.go | 304 ------------------ cmd/kubeadm/app/cmd/upgrade/common_test.go | 4 - .../app/phases/addons/proxy/proxy_test.go | 47 +-- .../phases/uploadconfig/uploadconfig_test.go | 33 +- .../app/util/config/masterconfig_test.go | 96 +++++- cmd/kubeadm/app/util/marshal_test.go | 24 +- 7 files changed, 162 insertions(+), 423 deletions(-) diff --git a/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go b/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go index 592401c2a80..5a0b1c5b9e5 100644 --- a/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go +++ b/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go @@ -25,10 +25,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" "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" + kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" utilpointer "k8s.io/kubernetes/pkg/util/pointer" ) @@ -40,11 +41,10 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { obj.KubernetesVersion = "v10" obj.API.BindPort = 20 obj.API.AdvertiseAddress = "foo" - obj.Networking.ServiceSubnet = "foo" - obj.Networking.DNSDomain = "foo" + obj.Networking.ServiceSubnet = "10.96.0.0/12" + obj.Networking.DNSDomain = "cluster.local" obj.CertificatesDir = "foo" obj.APIServerCertSANs = []string{"foo"} - obj.BootstrapTokens = []kubeadm.BootstrapToken{ { Token: &kubeadm.BootstrapTokenString{ @@ -68,9 +68,6 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { MountPath: "foo", Writable: false, }} - // Note: We don't set values here for obj.Etcd.External, as these are mutually exlusive. - // And to make sure the fuzzer doesn't set a random value for obj.Etcd.External, we let - // kubeadmapi.Etcd implement fuzz.Interface (we handle that ourselves) obj.Etcd.Local = &kubeadm.LocalEtcd{ Image: "foo", DataDir: "foo", @@ -83,65 +80,23 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { Name: "foo", Taints: []v1.Taint{}, } - extkubeletconfig := &kubeletconfigv1beta1.KubeletConfiguration{ - StaticPodPath: "foo", - ClusterDNS: []string{"foo"}, - ClusterDomain: "foo", - Authorization: kubeletconfigv1beta1.KubeletAuthorization{ - Mode: "Webhook", - }, - Authentication: kubeletconfigv1beta1.KubeletAuthentication{ - X509: kubeletconfigv1beta1.KubeletX509Authentication{ - ClientCAFile: "/etc/kubernetes/pki/ca.crt", - }, - Anonymous: kubeletconfigv1beta1.KubeletAnonymousAuthentication{ - Enabled: utilpointer.BoolPtr(false), - }, - }, - RotateCertificates: true, - } - obj.ComponentConfigs.Kubelet = &kubeletconfig.KubeletConfiguration{} - kubeletconfigv1beta1.SetDefaults_KubeletConfiguration(extkubeletconfig) - scheme, _, _ := kubeletconfigscheme.NewSchemeAndCodecs() - scheme.Convert(extkubeletconfig, obj.ComponentConfigs.Kubelet, nil) - obj.ComponentConfigs.KubeProxy = &kubeproxyconfig.KubeProxyConfiguration{ - FeatureGates: map[string]bool{"foo": true}, - BindAddress: "foo", - HealthzBindAddress: "foo:10256", - MetricsBindAddress: "foo:", - EnableProfiling: bool(true), - ClusterCIDR: "foo", - HostnameOverride: "foo", - ClientConnection: kubeproxyconfig.ClientConnectionConfiguration{ - KubeConfigFile: "foo", - AcceptContentTypes: "foo", - ContentType: "foo", - QPS: float32(5), - Burst: 10, - }, - IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ - SyncPeriod: metav1.Duration{Duration: 1}, - }, - IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ - MasqueradeBit: utilpointer.Int32Ptr(0), - SyncPeriod: metav1.Duration{Duration: 1}, - }, - OOMScoreAdj: utilpointer.Int32Ptr(0), - ResourceContainer: "foo", - UDPIdleTimeout: metav1.Duration{Duration: 1}, - Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ - MaxPerCore: utilpointer.Int32Ptr(2), - Min: utilpointer.Int32Ptr(1), - TCPEstablishedTimeout: &metav1.Duration{Duration: 5}, - TCPCloseWaitTimeout: &metav1.Duration{Duration: 5}, - }, - ConfigSyncPeriod: metav1.Duration{Duration: 1}, - } obj.AuditPolicyConfiguration = kubeadm.AuditPolicyConfiguration{ Path: "foo", LogDir: "/foo", LogMaxAge: utilpointer.Int32Ptr(0), } + // Set the Kubelet ComponentConfig to an empty, defaulted struct + extkubeletconfig := &kubeletconfigv1beta1.KubeletConfiguration{} + obj.ComponentConfigs.Kubelet = &kubeletconfig.KubeletConfiguration{} + componentconfigs.Scheme.Default(extkubeletconfig) + componentconfigs.Scheme.Convert(extkubeletconfig, obj.ComponentConfigs.Kubelet, nil) + componentconfigs.DefaultKubeletConfiguration(obj) + // Set the KubeProxy ComponentConfig to an empty, defaulted struct + extkubeproxyconfig := &kubeproxyconfigv1alpha1.KubeProxyConfiguration{} + obj.ComponentConfigs.KubeProxy = &kubeproxyconfig.KubeProxyConfiguration{} + componentconfigs.Scheme.Default(extkubeproxyconfig) + componentconfigs.Scheme.Convert(extkubeproxyconfig, obj.ComponentConfigs.KubeProxy, nil) + componentconfigs.DefaultKubeProxyConfiguration(obj) }, func(obj *kubeadm.NodeConfiguration, c fuzz.Continue) { c.FuzzNoCustom(obj) diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go b/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go index 75e81e7ac16..00d0d34c4b3 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go +++ b/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go @@ -19,7 +19,6 @@ package validation import ( "io/ioutil" "os" - "strings" "testing" "time" @@ -28,7 +27,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig" utilpointer "k8s.io/kubernetes/pkg/util/pointer" ) @@ -678,308 +676,6 @@ func TestValidateIgnorePreflightErrors(t *testing.T) { } } -func TestValidateKubeletConfiguration(t *testing.T) { - successCase := &kubeletconfig.KubeletConfiguration{ - CgroupsPerQOS: true, - EnforceNodeAllocatable: []string{"pods", "system-reserved", "kube-reserved"}, - SystemCgroups: "", - CgroupRoot: "", - EventBurst: 10, - EventRecordQPS: 5, - HealthzPort: 10248, - ImageGCHighThresholdPercent: 85, - ImageGCLowThresholdPercent: 80, - IPTablesDropBit: 15, - IPTablesMasqueradeBit: 14, - KubeAPIBurst: 10, - KubeAPIQPS: 5, - MaxOpenFiles: 1000000, - MaxPods: 110, - OOMScoreAdj: -999, - PodsPerCore: 100, - Port: 65535, - ReadOnlyPort: 0, - RegistryBurst: 10, - RegistryPullQPS: 5, - HairpinMode: "promiscuous-bridge", - } - if allErrors := ValidateKubeletConfiguration(successCase, nil); len(allErrors) != 0 { - t.Errorf("failed ValidateKubeletConfiguration: expect no errors but got %v", allErrors) - } - - errorCase := &kubeletconfig.KubeletConfiguration{ - CgroupsPerQOS: false, - EnforceNodeAllocatable: []string{"pods", "system-reserved", "kube-reserved", "illegal-key"}, - SystemCgroups: "/", - CgroupRoot: "", - EventBurst: -10, - EventRecordQPS: -10, - HealthzPort: -10, - ImageGCHighThresholdPercent: 101, - ImageGCLowThresholdPercent: 101, - IPTablesDropBit: -10, - IPTablesMasqueradeBit: -10, - KubeAPIBurst: -10, - KubeAPIQPS: -10, - MaxOpenFiles: -10, - MaxPods: -10, - OOMScoreAdj: -1001, - PodsPerCore: -10, - Port: 0, - ReadOnlyPort: -10, - RegistryBurst: -10, - RegistryPullQPS: -10, - } - if allErrors := ValidateKubeletConfiguration(errorCase, nil); len(allErrors) == 0 { - t.Errorf("failed ValidateKubeletConfiguration: expect errors but got no error") - } -} - -func TestValidateKubeProxyConfiguration(t *testing.T) { - successCases := []kubeadm.MasterConfiguration{ - { - ComponentConfigs: kubeadm.ComponentConfigs{ - KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ - BindAddress: "192.168.59.103", - HealthzBindAddress: "0.0.0.0:10256", - MetricsBindAddress: "127.0.0.1:10249", - ClusterCIDR: "192.168.59.0/24", - UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, - ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, - IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ - MasqueradeAll: true, - SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, - }, - IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ - SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - }, - Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ - Max: utilpointer.Int32Ptr(2), - MaxPerCore: utilpointer.Int32Ptr(1), - Min: utilpointer.Int32Ptr(1), - TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, - TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, - }, - }, - }, - }, - } - - for _, successCase := range successCases { - if errs := ValidateProxy(successCase.ComponentConfigs.KubeProxy, nil); len(errs) != 0 { - t.Errorf("failed ValidateProxy: expect no errors but got %v", errs) - } - } - - errorCases := []struct { - masterConfig kubeadm.MasterConfiguration - msg string - }{ - { - masterConfig: kubeadm.MasterConfiguration{ - ComponentConfigs: kubeadm.ComponentConfigs{ - KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ - // only BindAddress is invalid - BindAddress: "10.10.12.11:2000", - HealthzBindAddress: "0.0.0.0:10256", - MetricsBindAddress: "127.0.0.1:10249", - ClusterCIDR: "192.168.59.0/24", - UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, - ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, - IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ - MasqueradeAll: true, - SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, - }, - IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ - SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - }, - Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ - Max: utilpointer.Int32Ptr(2), - MaxPerCore: utilpointer.Int32Ptr(1), - Min: utilpointer.Int32Ptr(1), - TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, - TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, - }, - }, - }, - }, - msg: "not a valid textual representation of an IP address", - }, - { - masterConfig: kubeadm.MasterConfiguration{ - ComponentConfigs: kubeadm.ComponentConfigs{ - KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ - BindAddress: "10.10.12.11", - // only HealthzBindAddress is invalid - HealthzBindAddress: "0.0.0.0", - MetricsBindAddress: "127.0.0.1:10249", - ClusterCIDR: "192.168.59.0/24", - UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, - ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, - IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ - MasqueradeAll: true, - SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, - }, - IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ - SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - }, - Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ - Max: utilpointer.Int32Ptr(2), - MaxPerCore: utilpointer.Int32Ptr(1), - Min: utilpointer.Int32Ptr(1), - TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, - TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, - }, - }, - }, - }, - msg: "must be IP:port", - }, - { - masterConfig: kubeadm.MasterConfiguration{ - ComponentConfigs: kubeadm.ComponentConfigs{ - KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ - BindAddress: "10.10.12.11", - HealthzBindAddress: "0.0.0.0:12345", - // only MetricsBindAddress is invalid - MetricsBindAddress: "127.0.0.1", - ClusterCIDR: "192.168.59.0/24", - UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, - ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, - IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ - MasqueradeAll: true, - SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, - }, - IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ - SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - }, - Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ - Max: utilpointer.Int32Ptr(2), - MaxPerCore: utilpointer.Int32Ptr(1), - Min: utilpointer.Int32Ptr(1), - TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, - TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, - }, - }, - }, - }, - msg: "must be IP:port", - }, - { - masterConfig: kubeadm.MasterConfiguration{ - ComponentConfigs: kubeadm.ComponentConfigs{ - KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ - BindAddress: "10.10.12.11", - HealthzBindAddress: "0.0.0.0:12345", - MetricsBindAddress: "127.0.0.1:10249", - // only ClusterCIDR is invalid - ClusterCIDR: "192.168.59.0", - UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, - ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, - IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ - MasqueradeAll: true, - SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, - }, - IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ - SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - }, - Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ - Max: utilpointer.Int32Ptr(2), - MaxPerCore: utilpointer.Int32Ptr(1), - Min: utilpointer.Int32Ptr(1), - TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, - TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, - }, - }, - }, - }, - msg: "must be a valid CIDR block (e.g. 10.100.0.0/16)", - }, - { - masterConfig: kubeadm.MasterConfiguration{ - ComponentConfigs: kubeadm.ComponentConfigs{ - KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ - BindAddress: "10.10.12.11", - HealthzBindAddress: "0.0.0.0:12345", - MetricsBindAddress: "127.0.0.1:10249", - ClusterCIDR: "192.168.59.0/24", - // only UDPIdleTimeout is invalid - UDPIdleTimeout: metav1.Duration{Duration: -1 * time.Second}, - ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second}, - IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ - MasqueradeAll: true, - SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, - }, - IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ - SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - }, - Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ - Max: utilpointer.Int32Ptr(2), - MaxPerCore: utilpointer.Int32Ptr(1), - Min: utilpointer.Int32Ptr(1), - TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, - TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, - }, - }, - }, - }, - msg: "must be greater than 0", - }, - { - masterConfig: kubeadm.MasterConfiguration{ - ComponentConfigs: kubeadm.ComponentConfigs{ - KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ - BindAddress: "10.10.12.11", - HealthzBindAddress: "0.0.0.0:12345", - MetricsBindAddress: "127.0.0.1:10249", - ClusterCIDR: "192.168.59.0/24", - UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second}, - // only ConfigSyncPeriod is invalid - ConfigSyncPeriod: metav1.Duration{Duration: -1 * time.Second}, - IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{ - MasqueradeAll: true, - SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, - }, - IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ - SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, - MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, - }, - Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ - Max: utilpointer.Int32Ptr(2), - MaxPerCore: utilpointer.Int32Ptr(1), - Min: utilpointer.Int32Ptr(1), - TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, - TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, - }, - }, - }, - }, - msg: "must be greater than 0", - }, - } - - for i, errorCase := range errorCases { - if errs := ValidateProxy(errorCase.masterConfig.ComponentConfigs.KubeProxy, nil); len(errs) == 0 { - t.Errorf("%d failed ValidateProxy: expected error for %s, but got no error", i, errorCase.msg) - } else if !strings.Contains(errs[0].Error(), errorCase.msg) { - t.Errorf("%d failed ValidateProxy: unexpected error: %v, expected: %s", i, errs[0], errorCase.msg) - } - } -} - func TestValidateArgSelection(t *testing.T) { var tests = []struct { name string diff --git a/cmd/kubeadm/app/cmd/upgrade/common_test.go b/cmd/kubeadm/app/cmd/upgrade/common_test.go index 0175cad8903..d01b13e7d7d 100644 --- a/cmd/kubeadm/app/cmd/upgrade/common_test.go +++ b/cmd/kubeadm/app/cmd/upgrade/common_test.go @@ -58,8 +58,6 @@ func TestPrintConfiguration(t *testing.T) { image: "" imageRepository: "" kind: MasterConfiguration - kubeProxy: {} - kubeletConfiguration: {} kubernetesVersion: v1.7.1 networking: dnsDomain: "" @@ -100,8 +98,6 @@ func TestPrintConfiguration(t *testing.T) { keyFile: "" imageRepository: "" kind: MasterConfiguration - kubeProxy: {} - kubeletConfiguration: {} kubernetesVersion: v1.7.1 networking: dnsDomain: "" diff --git a/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go b/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go index 5b37f7f72a2..41675f25e28 100644 --- a/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go +++ b/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go @@ -28,9 +28,9 @@ import ( core "k8s.io/client-go/testing" kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" - cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" + configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" api "k8s.io/kubernetes/pkg/apis/core" - kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" + "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig" "k8s.io/kubernetes/pkg/util/pointer" ) @@ -173,32 +173,17 @@ func TestEnsureProxyAddon(t *testing.T) { // Create a fake client and set up default test configuration client := clientsetfake.NewSimpleClientset() - + // TODO: Consider using a YAML file instead for this that makes it possible to specify YAML documents for the ComponentConfigs masterConfig := &kubeadmapiv1alpha3.MasterConfiguration{ API: kubeadmapiv1alpha3.API{ AdvertiseAddress: "1.2.3.4", BindPort: 1234, }, - KubeProxy: kubeadmapiv1alpha3.KubeProxy{ - Config: &kubeproxyconfigv1alpha1.KubeProxyConfiguration{ - BindAddress: "", - HealthzBindAddress: "0.0.0.0:10256", - MetricsBindAddress: "127.0.0.1:10249", - Conntrack: kubeproxyconfigv1alpha1.KubeProxyConntrackConfiguration{ - Max: pointer.Int32Ptr(2), - MaxPerCore: pointer.Int32Ptr(1), - Min: pointer.Int32Ptr(1), - TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, - TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, - }, - }, - }, Networking: kubeadmapiv1alpha3.Networking{ PodSubnet: "5.6.7.8/24", }, - ImageRepository: "someRepo", - KubernetesVersion: "v1.10.0", - UnifiedControlPlaneImage: "someImage", + ImageRepository: "someRepo", + KubernetesVersion: "v1.10.0", } // Simulate an error if necessary @@ -214,10 +199,26 @@ func TestEnsureProxyAddon(t *testing.T) { masterConfig.Networking.PodSubnet = "2001:101::/96" } - kubeadmapiv1alpha3.SetDefaults_MasterConfiguration(masterConfig) - intMaster, err := cmdutil.ConfigFileAndDefaultsToInternalConfig("", masterConfig) + intMaster, err := configutil.ConfigFileAndDefaultsToInternalConfig("", masterConfig) if err != nil { - t.Errorf(" test failed to convert v1alpha1 to internal version") + t.Errorf("test failed to convert external to internal version") + break + } + intMaster.ComponentConfigs.KubeProxy = &kubeproxyconfig.KubeProxyConfiguration{ + BindAddress: "", + HealthzBindAddress: "0.0.0.0:10256", + MetricsBindAddress: "127.0.0.1:10249", + Conntrack: kubeproxyconfig.KubeProxyConntrackConfiguration{ + Max: pointer.Int32Ptr(2), + MaxPerCore: pointer.Int32Ptr(1), + Min: pointer.Int32Ptr(1), + TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second}, + TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second}, + }, + } + // Run dynamic defaulting again as we changed the internal cfg + if err := configutil.SetInitDynamicDefaults(intMaster); err != nil { + t.Errorf("test failed to set dynamic defaults: %v", err) break } err = EnsureProxyAddon(intMaster, client) diff --git a/cmd/kubeadm/app/phases/uploadconfig/uploadconfig_test.go b/cmd/kubeadm/app/phases/uploadconfig/uploadconfig_test.go index d987695f1dc..f88cf0063de 100644 --- a/cmd/kubeadm/app/phases/uploadconfig/uploadconfig_test.go +++ b/cmd/kubeadm/app/phases/uploadconfig/uploadconfig_test.go @@ -61,7 +61,7 @@ func TestUploadConfiguration(t *testing.T) { }, } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { + t.Run(tt.name, func(t2 *testing.T) { cfg := &kubeadmapi.MasterConfiguration{ KubernetesVersion: "v1.10.3", BootstrapTokens: []kubeadmapi.BootstrapToken{ @@ -85,7 +85,7 @@ func TestUploadConfiguration(t *testing.T) { } // For idempotent test, we check the result of the second call. if err := UploadConfiguration(cfg, client); !tt.updateExisting && (err != nil) != tt.errExpected { - t.Errorf("UploadConfiguration() error = %v, wantErr %v", err, tt.errExpected) + t2.Fatalf("UploadConfiguration() error = %v, wantErr %v", err, tt.errExpected) } if tt.updateExisting { if tt.errOnUpdate != nil { @@ -94,49 +94,36 @@ func TestUploadConfiguration(t *testing.T) { }) } if err := UploadConfiguration(cfg, client); (err != nil) != tt.errExpected { - t.Errorf("UploadConfiguration() error = %v", err) + t2.Fatalf("UploadConfiguration() error = %v", err) } } if tt.verifyResult { masterCfg, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(kubeadmconstants.MasterConfigurationConfigMap, metav1.GetOptions{}) if err != nil { - t.Errorf("Fail to query ConfigMap error = %v", err) + t2.Fatalf("Fail to query ConfigMap error = %v", err) } configData := masterCfg.Data[kubeadmconstants.MasterConfigurationConfigMapKey] if configData == "" { - t.Errorf("Fail to find ConfigMap key") + t2.Fatalf("Fail to find ConfigMap key") } - decodedExtCfg := &kubeadmapiv1alpha3.MasterConfiguration{} decodedCfg := &kubeadmapi.MasterConfiguration{} - - if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), []byte(configData), decodedExtCfg); err != nil { - t.Errorf("unable to decode config from bytes: %v", err) + if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), []byte(configData), decodedCfg); err != nil { + t2.Fatalf("unable to decode config from bytes: %v", err) } - // Default and convert to the internal version - kubeadmscheme.Scheme.Default(decodedExtCfg) - kubeadmscheme.Scheme.Convert(decodedExtCfg, decodedCfg, nil) if decodedCfg.KubernetesVersion != cfg.KubernetesVersion { - t.Errorf("Decoded value doesn't match, decoded = %#v, expected = %#v", decodedCfg.KubernetesVersion, cfg.KubernetesVersion) + t2.Errorf("Decoded value doesn't match, decoded = %#v, expected = %#v", decodedCfg.KubernetesVersion, cfg.KubernetesVersion) } // If the decoded cfg has a BootstrapTokens array, verify the sensitive information we had isn't still there. if len(decodedCfg.BootstrapTokens) > 0 && decodedCfg.BootstrapTokens[0].Token != nil && decodedCfg.BootstrapTokens[0].Token.String() == cfg.BootstrapTokens[0].Token.String() { - t.Errorf("Decoded value contains .BootstrapTokens (sensitive info), decoded = %#v, expected = empty", decodedCfg.BootstrapTokens) + t2.Errorf("Decoded value contains .BootstrapTokens (sensitive info), decoded = %#v, expected = empty", decodedCfg.BootstrapTokens) } // Make sure no information from NodeRegistrationOptions was uploaded. if decodedCfg.NodeRegistration.Name == cfg.NodeRegistration.Name || decodedCfg.NodeRegistration.CRISocket != kubeadmapiv1alpha3.DefaultCRISocket { - t.Errorf("Decoded value contains .NodeRegistration (node-specific info shouldn't be uploaded), decoded = %#v, expected = empty", decodedCfg.NodeRegistration) - } - - if decodedExtCfg.Kind != "MasterConfiguration" { - t.Errorf("Expected kind MasterConfiguration, got %v", decodedExtCfg.Kind) - } - - if decodedExtCfg.APIVersion != "kubeadm.k8s.io/v1alpha3" { - t.Errorf("Expected apiVersion kubeadm.k8s.io/v1alpha3, got %v", decodedExtCfg.APIVersion) + t2.Errorf("Decoded value contains .NodeRegistration (node-specific info shouldn't be uploaded), decoded = %#v, expected = empty", decodedCfg.NodeRegistration) } } }) diff --git a/cmd/kubeadm/app/util/config/masterconfig_test.go b/cmd/kubeadm/app/util/config/masterconfig_test.go index 291ffe0d0cf..c53efbb4698 100644 --- a/cmd/kubeadm/app/util/config/masterconfig_test.go +++ b/cmd/kubeadm/app/util/config/masterconfig_test.go @@ -19,15 +19,14 @@ package config import ( "bytes" "io/ioutil" + "reflect" "testing" "github.com/pmezard/go-difflib/difflib" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3" - kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" ) const ( @@ -87,7 +86,7 @@ func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) { // These tests are reading one file that has only a subset of the fields populated, loading it using ConfigFileAndDefaultsToInternalConfig, // and then marshals the internal object to the expected groupVersion { // v1alpha2 -> default -> validate -> internal -> v1alpha3 - name: "incompleteYAMLToDefaultedv1alpha2", + name: "incompleteYAMLToDefaultedv1alpha3", in: master_incompleteYAML, out: master_defaultedYAML, groupVersion: kubeadmapiv1alpha3.SchemeGroupVersion, @@ -110,7 +109,7 @@ func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) { t2.Fatalf("couldn't unmarshal test data: %v", err) } - actual, err := kubeadmutil.MarshalToYamlForCodecs(internalcfg, rt.groupVersion, scheme.Codecs) + actual, err := MarshalMasterConfigurationToBytes(internalcfg, rt.groupVersion) if err != nil { t2.Fatalf("couldn't marshal internal object: %v", err) } @@ -127,3 +126,92 @@ func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) { }) } } + +func TestConsistentOrderByteSlice(t *testing.T) { + var ( + aKind = "Akind" + aFile = []byte(` +kind: Akind +apiVersion: foo.k8s.io/v1 +`) + aaKind = "Aakind" + aaFile = []byte(` +kind: Aakind +apiVersion: foo.k8s.io/v1 +`) + abKind = "Abkind" + abFile = []byte(` +kind: Abkind +apiVersion: foo.k8s.io/v1 +`) + ) + var tests = []struct { + name string + in map[string][]byte + expected [][]byte + }{ + { + name: "a_aa_ab", + in: map[string][]byte{ + aKind: aFile, + aaKind: aaFile, + abKind: abFile, + }, + expected: [][]byte{aaFile, abFile, aFile}, + }, + { + name: "a_ab_aa", + in: map[string][]byte{ + aKind: aFile, + abKind: abFile, + aaKind: aaFile, + }, + expected: [][]byte{aaFile, abFile, aFile}, + }, + { + name: "aa_a_ab", + in: map[string][]byte{ + aaKind: aaFile, + aKind: aFile, + abKind: abFile, + }, + expected: [][]byte{aaFile, abFile, aFile}, + }, + { + name: "aa_ab_a", + in: map[string][]byte{ + aaKind: aaFile, + abKind: abFile, + aKind: aFile, + }, + expected: [][]byte{aaFile, abFile, aFile}, + }, + { + name: "ab_a_aa", + in: map[string][]byte{ + abKind: abFile, + aKind: aFile, + aaKind: aaFile, + }, + expected: [][]byte{aaFile, abFile, aFile}, + }, + { + name: "ab_aa_a", + in: map[string][]byte{ + abKind: abFile, + aaKind: aaFile, + aKind: aFile, + }, + expected: [][]byte{aaFile, abFile, aFile}, + }, + } + + for _, rt := range tests { + t.Run(rt.name, func(t2 *testing.T) { + actual := consistentOrderByteSlice(rt.in) + if !reflect.DeepEqual(rt.expected, actual) { + t2.Errorf("the expected and actual output differs.\n\texpected: %s\n\tout: %s\n", rt.expected, actual) + } + }) + } +} diff --git a/cmd/kubeadm/app/util/marshal_test.go b/cmd/kubeadm/app/util/marshal_test.go index d92b4cd0d6d..a06ff9f6162 100644 --- a/cmd/kubeadm/app/util/marshal_test.go +++ b/cmd/kubeadm/app/util/marshal_test.go @@ -24,8 +24,9 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" + "k8s.io/apimachinery/pkg/runtime/serializer" kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3" "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) @@ -125,16 +126,25 @@ func TestMarshalUnmarshalToYamlForCodecs(t *testing.T) { ServiceSubnet: "10.100.0.0/24", PodSubnet: "10.100.1.0/24", }, + BootstrapTokens: []kubeadmapiv1alpha3.BootstrapToken{ + { + Token: &kubeadmapiv1alpha3.BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, + }, + }, } - scheme.Scheme.Default(cfg) - bytes, err := MarshalToYamlForCodecs(cfg, kubeadmapiv1alpha3.SchemeGroupVersion, scheme.Codecs) + kubeadmapiv1alpha3.SetDefaults_MasterConfiguration(cfg) + scheme := runtime.NewScheme() + kubeadmapiv1alpha3.AddToScheme(scheme) + codecs := serializer.NewCodecFactory(scheme) + + bytes, err := MarshalToYamlForCodecs(cfg, kubeadmapiv1alpha3.SchemeGroupVersion, codecs) if err != nil { t.Fatalf("unexpected error marshalling MasterConfiguration: %v", err) } t.Logf("\n%s", bytes) - obj, err := UnmarshalFromYamlForCodecs(bytes, kubeadmapiv1alpha3.SchemeGroupVersion, scheme.Codecs) + obj, err := UnmarshalFromYamlForCodecs(bytes, kubeadmapiv1alpha3.SchemeGroupVersion, codecs) if err != nil { t.Fatalf("unexpected error unmarshalling MasterConfiguration: %v", err) } @@ -148,6 +158,12 @@ func TestMarshalUnmarshalToYamlForCodecs(t *testing.T) { } } +// {{MasterConfiguration kubeadm.k8s.io/v1alpha3} [{ nil [] []}] {testNode /var/run/cri.sock [] map[]} {10.100.0.1 4332} {0xc4200ad2c0 } {10.100.0.0/24 10.100.1.0/24 cluster.local} stable-1.11 map[] map[] map[] [] [] [] [] /etc/kubernetes/pki k8s.gcr.io { /var/log/kubernetes/audit 0x156e2f4} map[] kubernetes} +// {{MasterConfiguration kubeadm.k8s.io/v1alpha3} [{ &Duration{Duration:24h0m0s,} [signing authentication] [system:bootstrappers:kubeadm:default-node-token]}] {testNode /var/run/cri.sock [] map[]} {10.100.0.1 4332} {0xc4205c5260 } {10.100.0.0/24 10.100.1.0/24 cluster.local} stable-1.11 map[] map[] map[] [] [] [] [] /etc/kubernetes/pki k8s.gcr.io { /var/log/kubernetes/audit 0xc4204dd82c} map[] kubernetes} + +// {{MasterConfiguration kubeadm.k8s.io/v1alpha3} [{abcdef.abcdef0123456789 nil [] []}] {testNode /var/run/cri.sock [] map[]} {10.100.0.1 4332} {0xc42012ca80 } {10.100.0.0/24 10.100.1.0/24 cluster.local} stable-1.11 map[] map[] map[] [] [] [] [] /etc/kubernetes/pki k8s.gcr.io { /var/log/kubernetes/audit 0x156e2f4} map[] kubernetes} +// {{MasterConfiguration kubeadm.k8s.io/v1alpha3} [{abcdef.abcdef0123456789 &Duration{Duration:24h0m0s,} [signing authentication] [system:bootstrappers:kubeadm:default-node-token]}] {testNode /var/run/cri.sock [] map[]} {10.100.0.1 4332} {0xc42039d1a0 } {10.100.0.0/24 10.100.1.0/24 cluster.local} stable-1.11 map[] map[] map[] [] [] [] [] /etc/kubernetes/pki k8s.gcr.io { /var/log/kubernetes/audit 0xc4204fef3c} map[] kubernetes} + func TestSplitYAMLDocuments(t *testing.T) { var tests = []struct { name string From 699949fc87ddb54a1782ed70cf913eaf65583940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Sun, 8 Jul 2018 21:33:28 +0300 Subject: [PATCH 5/6] Update the kubeadm config API roundtrip yaml files --- .../testdata/conversion/master/v1alpha3.yaml | 222 +++++++++--------- .../testdata/defaulting/master/defaulted.yaml | 218 ++++++++--------- .../defaulting/master/incomplete.yaml | 1 + 3 files changed, 223 insertions(+), 218 deletions(-) diff --git a/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha3.yaml b/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha3.yaml index 8a20ba41b50..cc9952ed3b3 100644 --- a/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha3.yaml +++ b/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha3.yaml @@ -25,116 +25,6 @@ etcd: image: "" imageRepository: k8s.gcr.io kind: MasterConfiguration -kubeProxy: - config: - bindAddress: 0.0.0.0 - clientConnection: - acceptContentTypes: "" - burst: 10 - contentType: application/vnd.kubernetes.protobuf - kubeconfig: /var/lib/kube-proxy/kubeconfig.conf - qps: 5 - clusterCIDR: "" - configSyncPeriod: 15m0s - conntrack: - max: null - maxPerCore: 32768 - min: 131072 - tcpCloseWaitTimeout: 1h0m0s - tcpEstablishedTimeout: 24h0m0s - enableProfiling: false - featureGates: - ServiceNodeExclusion: true - SupportIPVSProxyMode: true - healthzBindAddress: 0.0.0.0:10256 - hostnameOverride: "" - iptables: - masqueradeAll: false - masqueradeBit: 14 - minSyncPeriod: 0s - syncPeriod: 30s - ipvs: - excludeCIDRs: null - minSyncPeriod: 0s - scheduler: "" - syncPeriod: 30s - metricsBindAddress: 127.0.0.1:10249 - mode: iptables - nodePortAddresses: null - oomScoreAdj: -999 - portRange: "" - resourceContainer: /kube-proxy - udpIdleTimeout: 250ms -kubeletConfiguration: - baseConfig: - address: 1.2.3.4 - authentication: - anonymous: - enabled: false - webhook: - cacheTTL: 2m0s - enabled: true - x509: - clientCAFile: /etc/kubernetes/pki/ca.crt - authorization: - mode: Webhook - webhook: - cacheAuthorizedTTL: 5m0s - cacheUnauthorizedTTL: 30s - cgroupDriver: cgroupfs - cgroupsPerQOS: true - clusterDNS: - - 10.96.0.10 - clusterDomain: cluster.local - configMapAndSecretChangeDetectionStrategy: Watch - containerLogMaxFiles: 5 - containerLogMaxSize: 10Mi - contentType: application/vnd.kubernetes.protobuf - cpuCFSQuota: true - cpuManagerPolicy: none - cpuManagerReconcilePeriod: 10s - enableControllerAttachDetach: true - enableDebuggingHandlers: true - enforceNodeAllocatable: - - pods - eventBurst: 10 - eventRecordQPS: 5 - evictionHard: - imagefs.available: 15% - memory.available: 100Mi - nodefs.available: 10% - nodefs.inodesFree: 5% - evictionPressureTransitionPeriod: 5m0s - failSwapOn: true - fileCheckFrequency: 20s - hairpinMode: promiscuous-bridge - healthzBindAddress: 127.0.0.1 - healthzPort: 10248 - httpCheckFrequency: 20s - imageGCHighThresholdPercent: 85 - imageGCLowThresholdPercent: 80 - imageMinimumGCAge: 2m0s - iptablesDropBit: 15 - iptablesMasqueradeBit: 14 - kubeAPIBurst: 10 - kubeAPIQPS: 5 - makeIPTablesUtilChains: true - maxOpenFiles: 1000000 - maxPods: 110 - nodeStatusUpdateFrequency: 10s - oomScoreAdj: -999 - podPidsLimit: -1 - port: 10250 - registryBurst: 10 - registryPullQPS: 5 - resolvConf: /etc/resolv.conf - rotateCertificates: true - runtimeRequestTimeout: 2m0s - serializeImagePulls: true - staticPodPath: /etc/kubernetes/manifests - streamingConnectionIdleTimeout: 4h0m0s - syncFrequency: 1m0s - volumeStatsAggPeriod: 1m0s kubernetesVersion: v1.10.2 networking: dnsDomain: cluster.local @@ -147,3 +37,115 @@ nodeRegistration: - effect: NoSchedule key: node-role.kubernetes.io/master unifiedControlPlaneImage: "" +--- +apiVersion: kubeproxy.config.k8s.io/v1alpha1 +bindAddress: 0.0.0.0 +clientConnection: + acceptContentTypes: "" + burst: 10 + contentType: application/vnd.kubernetes.protobuf + kubeconfig: /var/lib/kube-proxy/kubeconfig.conf + qps: 5 +clusterCIDR: "" +configSyncPeriod: 15m0s +conntrack: + max: null + maxPerCore: 32768 + min: 131072 + tcpCloseWaitTimeout: 1h0m0s + tcpEstablishedTimeout: 24h0m0s +enableProfiling: false +featureGates: + ServiceNodeExclusion: true + SupportIPVSProxyMode: true +healthzBindAddress: 0.0.0.0:10256 +hostnameOverride: "" +iptables: + masqueradeAll: false + masqueradeBit: 14 + minSyncPeriod: 0s + syncPeriod: 30s +ipvs: + excludeCIDRs: null + minSyncPeriod: 0s + scheduler: "" + syncPeriod: 30s +kind: KubeProxyConfiguration +metricsBindAddress: 127.0.0.1:10249 +mode: iptables +nodePortAddresses: null +oomScoreAdj: -999 +portRange: "" +resourceContainer: /kube-proxy +udpIdleTimeout: 250ms +--- +address: 1.2.3.4 +apiVersion: kubelet.config.k8s.io/v1beta1 +authentication: + anonymous: + enabled: false + webhook: + cacheTTL: 2m0s + enabled: true + x509: + clientCAFile: /etc/kubernetes/pki/ca.crt +authorization: + mode: Webhook + webhook: + cacheAuthorizedTTL: 5m0s + cacheUnauthorizedTTL: 30s +cgroupDriver: cgroupfs +cgroupsPerQOS: true +clusterDNS: +- 10.96.0.10 +clusterDomain: cluster.local +configMapAndSecretChangeDetectionStrategy: Watch +containerLogMaxFiles: 5 +containerLogMaxSize: 10Mi +contentType: application/vnd.kubernetes.protobuf +cpuCFSQuota: true +cpuManagerPolicy: none +cpuManagerReconcilePeriod: 10s +enableControllerAttachDetach: true +enableDebuggingHandlers: true +enforceNodeAllocatable: +- pods +eventBurst: 10 +eventRecordQPS: 5 +evictionHard: + imagefs.available: 15% + memory.available: 100Mi + nodefs.available: 10% + nodefs.inodesFree: 5% +evictionPressureTransitionPeriod: 5m0s +failSwapOn: true +fileCheckFrequency: 20s +hairpinMode: promiscuous-bridge +healthzBindAddress: 127.0.0.1 +healthzPort: 10248 +httpCheckFrequency: 20s +imageGCHighThresholdPercent: 85 +imageGCLowThresholdPercent: 80 +imageMinimumGCAge: 2m0s +iptablesDropBit: 15 +iptablesMasqueradeBit: 14 +kind: KubeletConfiguration +kubeAPIBurst: 10 +kubeAPIQPS: 5 +makeIPTablesUtilChains: true +maxOpenFiles: 1000000 +maxPods: 110 +nodeStatusUpdateFrequency: 10s +oomScoreAdj: -999 +podPidsLimit: -1 +port: 10250 +registryBurst: 10 +registryPullQPS: 5 +resolvConf: /etc/resolv.conf +rotateCertificates: true +runtimeRequestTimeout: 2m0s +serializeImagePulls: true +staticPodPath: /etc/kubernetes/manifests +streamingConnectionIdleTimeout: 4h0m0s +syncFrequency: 1m0s +volumeStatsAggPeriod: 1m0s diff --git a/cmd/kubeadm/app/util/config/testdata/defaulting/master/defaulted.yaml b/cmd/kubeadm/app/util/config/testdata/defaulting/master/defaulted.yaml index fa9436b837f..98f35196a89 100644 --- a/cmd/kubeadm/app/util/config/testdata/defaulting/master/defaulted.yaml +++ b/cmd/kubeadm/app/util/config/testdata/defaulting/master/defaulted.yaml @@ -23,117 +23,10 @@ etcd: image: "" imageRepository: my-company.com kind: MasterConfiguration -kubeProxy: - config: - bindAddress: 0.0.0.0 - clientConnection: - acceptContentTypes: "" - burst: 10 - contentType: application/vnd.kubernetes.protobuf - kubeconfig: /var/lib/kube-proxy/kubeconfig.conf - qps: 5 - clusterCIDR: "" - configSyncPeriod: 15m0s - conntrack: - max: null - maxPerCore: 32768 - min: 131072 - tcpCloseWaitTimeout: 1h0m0s - tcpEstablishedTimeout: 24h0m0s - enableProfiling: false - healthzBindAddress: 0.0.0.0:10256 - hostnameOverride: "" - iptables: - masqueradeAll: false - masqueradeBit: 14 - minSyncPeriod: 0s - syncPeriod: 30s - ipvs: - excludeCIDRs: null - minSyncPeriod: 0s - scheduler: "" - syncPeriod: 30s - metricsBindAddress: 127.0.0.1:10249 - mode: "" - nodePortAddresses: null - oomScoreAdj: -999 - portRange: "" - resourceContainer: /kube-proxy - udpIdleTimeout: 250ms -kubeletConfiguration: - baseConfig: - address: 0.0.0.0 - authentication: - anonymous: - enabled: false - webhook: - cacheTTL: 2m0s - enabled: true - x509: - clientCAFile: /etc/kubernetes/pki/ca.crt - authorization: - mode: Webhook - webhook: - cacheAuthorizedTTL: 5m0s - cacheUnauthorizedTTL: 30s - cgroupDriver: cgroupfs - cgroupsPerQOS: true - clusterDNS: - - 10.192.0.10 - clusterDomain: cluster.global - configMapAndSecretChangeDetectionStrategy: Watch - containerLogMaxFiles: 5 - containerLogMaxSize: 10Mi - contentType: application/vnd.kubernetes.protobuf - cpuCFSQuota: true - cpuManagerPolicy: none - cpuManagerReconcilePeriod: 10s - enableControllerAttachDetach: true - enableDebuggingHandlers: true - enforceNodeAllocatable: - - pods - eventBurst: 10 - eventRecordQPS: 5 - evictionHard: - imagefs.available: 15% - memory.available: 100Mi - nodefs.available: 10% - nodefs.inodesFree: 5% - evictionPressureTransitionPeriod: 5m0s - failSwapOn: true - fileCheckFrequency: 20s - hairpinMode: promiscuous-bridge - healthzBindAddress: 127.0.0.1 - healthzPort: 10248 - httpCheckFrequency: 20s - imageGCHighThresholdPercent: 85 - imageGCLowThresholdPercent: 80 - imageMinimumGCAge: 2m0s - iptablesDropBit: 15 - iptablesMasqueradeBit: 14 - kubeAPIBurst: 10 - kubeAPIQPS: 5 - makeIPTablesUtilChains: true - maxOpenFiles: 1000000 - maxPods: 110 - nodeStatusUpdateFrequency: 10s - oomScoreAdj: -999 - podPidsLimit: -1 - port: 10250 - registryBurst: 10 - registryPullQPS: 5 - resolvConf: /etc/resolv.conf - rotateCertificates: true - runtimeRequestTimeout: 2m0s - serializeImagePulls: true - staticPodPath: /etc/kubernetes/manifests - streamingConnectionIdleTimeout: 4h0m0s - syncFrequency: 1m0s - volumeStatsAggPeriod: 1m0s kubernetesVersion: v1.10.2 networking: dnsDomain: cluster.global - podSubnet: "" + podSubnet: 10.148.0.0/16 serviceSubnet: 10.196.0.0/12 nodeRegistration: criSocket: /var/run/criruntime.sock @@ -142,3 +35,112 @@ nodeRegistration: - effect: NoSchedule key: node-role.kubernetes.io/master unifiedControlPlaneImage: "" +--- +apiVersion: kubeproxy.config.k8s.io/v1alpha1 +bindAddress: 0.0.0.0 +clientConnection: + acceptContentTypes: "" + burst: 10 + contentType: application/vnd.kubernetes.protobuf + kubeconfig: /var/lib/kube-proxy/kubeconfig.conf + qps: 5 +clusterCIDR: 10.148.0.0/16 +configSyncPeriod: 15m0s +conntrack: + max: null + maxPerCore: 32768 + min: 131072 + tcpCloseWaitTimeout: 1h0m0s + tcpEstablishedTimeout: 24h0m0s +enableProfiling: false +healthzBindAddress: 0.0.0.0:10256 +hostnameOverride: "" +iptables: + masqueradeAll: false + masqueradeBit: 14 + minSyncPeriod: 0s + syncPeriod: 30s +ipvs: + excludeCIDRs: null + minSyncPeriod: 0s + scheduler: "" + syncPeriod: 30s +kind: KubeProxyConfiguration +metricsBindAddress: 127.0.0.1:10249 +mode: "" +nodePortAddresses: null +oomScoreAdj: -999 +portRange: "" +resourceContainer: /kube-proxy +udpIdleTimeout: 250ms +--- +address: 0.0.0.0 +apiVersion: kubelet.config.k8s.io/v1beta1 +authentication: + anonymous: + enabled: false + webhook: + cacheTTL: 2m0s + enabled: true + x509: + clientCAFile: /etc/kubernetes/pki/ca.crt +authorization: + mode: Webhook + webhook: + cacheAuthorizedTTL: 5m0s + cacheUnauthorizedTTL: 30s +cgroupDriver: cgroupfs +cgroupsPerQOS: true +clusterDNS: +- 10.192.0.10 +clusterDomain: cluster.global +configMapAndSecretChangeDetectionStrategy: Watch +containerLogMaxFiles: 5 +containerLogMaxSize: 10Mi +contentType: application/vnd.kubernetes.protobuf +cpuCFSQuota: true +cpuManagerPolicy: none +cpuManagerReconcilePeriod: 10s +enableControllerAttachDetach: true +enableDebuggingHandlers: true +enforceNodeAllocatable: +- pods +eventBurst: 10 +eventRecordQPS: 5 +evictionHard: + imagefs.available: 15% + memory.available: 100Mi + nodefs.available: 10% + nodefs.inodesFree: 5% +evictionPressureTransitionPeriod: 5m0s +failSwapOn: true +fileCheckFrequency: 20s +hairpinMode: promiscuous-bridge +healthzBindAddress: 127.0.0.1 +healthzPort: 10248 +httpCheckFrequency: 20s +imageGCHighThresholdPercent: 85 +imageGCLowThresholdPercent: 80 +imageMinimumGCAge: 2m0s +iptablesDropBit: 15 +iptablesMasqueradeBit: 14 +kind: KubeletConfiguration +kubeAPIBurst: 10 +kubeAPIQPS: 5 +makeIPTablesUtilChains: true +maxOpenFiles: 1000000 +maxPods: 110 +nodeStatusUpdateFrequency: 10s +oomScoreAdj: -999 +podPidsLimit: -1 +port: 10250 +registryBurst: 10 +registryPullQPS: 5 +resolvConf: /etc/resolv.conf +rotateCertificates: true +runtimeRequestTimeout: 2m0s +serializeImagePulls: true +staticPodPath: /etc/kubernetes/manifests +streamingConnectionIdleTimeout: 4h0m0s +syncFrequency: 1m0s +volumeStatsAggPeriod: 1m0s diff --git a/cmd/kubeadm/app/util/config/testdata/defaulting/master/incomplete.yaml b/cmd/kubeadm/app/util/config/testdata/defaulting/master/incomplete.yaml index b6f52265344..15b78937f3c 100644 --- a/cmd/kubeadm/app/util/config/testdata/defaulting/master/incomplete.yaml +++ b/cmd/kubeadm/app/util/config/testdata/defaulting/master/incomplete.yaml @@ -12,6 +12,7 @@ kubernetesVersion: v1.10.2 networking: dnsDomain: cluster.global serviceSubnet: 10.196.0.0/12 + podSubnet: 10.148.0.0/16 nodeRegistration: criSocket: /var/run/criruntime.sock name: master-1 From 0be8955466232437927e403a7e9462da48aa9ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Sun, 8 Jul 2018 21:33:56 +0300 Subject: [PATCH 6/6] autogenerated --- cmd/kubeadm/app/BUILD | 1 + cmd/kubeadm/app/apis/kubeadm/BUILD | 1 + cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD | 3 +- cmd/kubeadm/app/apis/kubeadm/v1alpha2/BUILD | 1 + .../v1alpha2/zz_generated.conversion.go | 2 +- cmd/kubeadm/app/apis/kubeadm/v1alpha3/BUILD | 1 - .../v1alpha3/zz_generated.conversion.go | 9 ++- .../kubeadm/v1alpha3/zz_generated.deepcopy.go | 46 --------------- .../kubeadm/v1alpha3/zz_generated.defaults.go | 8 --- cmd/kubeadm/app/apis/kubeadm/validation/BUILD | 6 +- cmd/kubeadm/app/cmd/upgrade/BUILD | 1 - cmd/kubeadm/app/componentconfigs/BUILD | 59 +++++++++++++++++++ cmd/kubeadm/app/phases/addons/proxy/BUILD | 5 +- cmd/kubeadm/app/phases/kubelet/BUILD | 3 +- cmd/kubeadm/app/phases/uploadconfig/BUILD | 4 +- cmd/kubeadm/app/util/BUILD | 3 +- cmd/kubeadm/app/util/config/BUILD | 2 + 17 files changed, 80 insertions(+), 75 deletions(-) create mode 100644 cmd/kubeadm/app/componentconfigs/BUILD diff --git a/cmd/kubeadm/app/BUILD b/cmd/kubeadm/app/BUILD index e67cc100a23..b3411caef40 100644 --- a/cmd/kubeadm/app/BUILD +++ b/cmd/kubeadm/app/BUILD @@ -30,6 +30,7 @@ filegroup( ":package-srcs", "//cmd/kubeadm/app/apis/kubeadm:all-srcs", "//cmd/kubeadm/app/cmd:all-srcs", + "//cmd/kubeadm/app/componentconfigs:all-srcs", "//cmd/kubeadm/app/constants:all-srcs", "//cmd/kubeadm/app/discovery:all-srcs", "//cmd/kubeadm/app/features:all-srcs", diff --git a/cmd/kubeadm/app/apis/kubeadm/BUILD b/cmd/kubeadm/app/apis/kubeadm/BUILD index 71a7c91ddb8..b9079c3b2cf 100644 --- a/cmd/kubeadm/app/apis/kubeadm/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/BUILD @@ -26,6 +26,7 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", "//staging/src/k8s.io/client-go/tools/bootstrap/token/util:go_default_library", + "//vendor/github.com/google/gofuzz:go_default_library", ], ) diff --git a/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD b/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD index 5b9f4a0fe50..c5cb9ac1c87 100644 --- a/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD @@ -12,10 +12,11 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer", deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/componentconfigs:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", "//pkg/proxy/apis/kubeproxyconfig:go_default_library", + "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", "//pkg/util/pointer:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/BUILD b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/BUILD index 3dee378e807..87c3fd48474 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/BUILD @@ -19,6 +19,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/componentconfigs:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.conversion.go index f50a72d46cd..34e3f4fd9d6 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha2/zz_generated.conversion.go @@ -309,7 +309,7 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration(in if err := Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { return err } - // WARNING: in.ComponentConfigs requires manual conversion: does not exist in peer-type + // INFO: in.ComponentConfigs opted out of conversion generation if err := Convert_kubeadm_API_To_v1alpha2_API(&in.API, &out.API, s); err != nil { return err } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/BUILD b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/BUILD index 8558b759fe4..a687d7f7c27 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/BUILD @@ -26,7 +26,6 @@ go_library( "//pkg/proxy/apis/kubeproxyconfig:go_default_library", "//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library", "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", - "//pkg/util/pointer:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library", diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.conversion.go index 984bfe1e7f8..2ea4d0f5a3e 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.conversion.go @@ -277,11 +277,9 @@ func autoConvert_v1alpha3_MasterConfiguration_To_kubeadm_MasterConfiguration(in if err := Convert_v1alpha3_API_To_kubeadm_API(&in.API, &out.API, s); err != nil { return err } - // WARNING: in.KubeProxy requires manual conversion: does not exist in peer-type if err := Convert_v1alpha3_Etcd_To_kubeadm_Etcd(&in.Etcd, &out.Etcd, s); err != nil { return err } - // WARNING: in.KubeletConfiguration requires manual conversion: does not exist in peer-type if err := Convert_v1alpha3_Networking_To_kubeadm_Networking(&in.Networking, &out.Networking, s); err != nil { return err } @@ -309,7 +307,7 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha3_MasterConfiguration(in if err := Convert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { return err } - // WARNING: in.ComponentConfigs requires manual conversion: does not exist in peer-type + // INFO: in.ComponentConfigs opted out of conversion generation if err := Convert_kubeadm_API_To_v1alpha3_API(&in.API, &out.API, s); err != nil { return err } @@ -339,6 +337,11 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha3_MasterConfiguration(in return nil } +// Convert_kubeadm_MasterConfiguration_To_v1alpha3_MasterConfiguration is an autogenerated conversion function. +func Convert_kubeadm_MasterConfiguration_To_v1alpha3_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error { + return autoConvert_kubeadm_MasterConfiguration_To_v1alpha3_MasterConfiguration(in, out, s) +} + func autoConvert_v1alpha3_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error { out.ServiceSubnet = in.ServiceSubnet out.PodSubnet = in.PodSubnet diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.deepcopy.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.deepcopy.go index a5a02a692cc..46171fbde1e 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.deepcopy.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.deepcopy.go @@ -24,8 +24,6 @@ import ( corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" - v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" - v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -184,48 +182,6 @@ func (in *HostPathMount) DeepCopy() *HostPathMount { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *KubeProxy) DeepCopyInto(out *KubeProxy) { - *out = *in - if in.Config != nil { - in, out := &in.Config, &out.Config - *out = new(v1alpha1.KubeProxyConfiguration) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeProxy. -func (in *KubeProxy) DeepCopy() *KubeProxy { - if in == nil { - return nil - } - out := new(KubeProxy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) { - *out = *in - if in.BaseConfig != nil { - in, out := &in.BaseConfig, &out.BaseConfig - *out = new(v1beta1.KubeletConfiguration) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeletConfiguration. -func (in *KubeletConfiguration) DeepCopy() *KubeletConfiguration { - if in == nil { - return nil - } - out := new(KubeletConfiguration) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LocalEtcd) DeepCopyInto(out *LocalEtcd) { *out = *in @@ -272,9 +228,7 @@ func (in *MasterConfiguration) DeepCopyInto(out *MasterConfiguration) { } in.NodeRegistration.DeepCopyInto(&out.NodeRegistration) out.API = in.API - in.KubeProxy.DeepCopyInto(&out.KubeProxy) in.Etcd.DeepCopyInto(&out.Etcd) - in.KubeletConfiguration.DeepCopyInto(&out.KubeletConfiguration) out.Networking = in.Networking if in.APIServerExtraArgs != nil { in, out := &in.APIServerExtraArgs, &out.APIServerExtraArgs diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.defaults.go index daedf3c522a..5454e5d95dc 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/zz_generated.defaults.go @@ -22,8 +22,6 @@ package v1alpha3 import ( runtime "k8s.io/apimachinery/pkg/runtime" - v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" - v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" ) // RegisterDefaults adds defaulters functions to the given scheme. @@ -42,12 +40,6 @@ func SetObjectDefaults_MasterConfiguration(in *MasterConfiguration) { SetDefaults_BootstrapToken(a) } SetDefaults_NodeRegistrationOptions(&in.NodeRegistration) - if in.KubeProxy.Config != nil { - v1alpha1.SetDefaults_KubeProxyConfiguration(in.KubeProxy.Config) - } - if in.KubeletConfiguration.BaseConfig != nil { - v1beta1.SetDefaults_KubeletConfiguration(in.KubeletConfiguration.BaseConfig) - } } func SetObjectDefaults_NodeConfiguration(in *NodeConfiguration) { diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/BUILD b/cmd/kubeadm/app/apis/kubeadm/validation/BUILD index 29a4e2aa60d..bd6c109e183 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/validation/BUILD @@ -7,14 +7,11 @@ go_library( visibility = ["//visibility:public"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/componentconfigs:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//pkg/apis/core/validation:go_default_library", - "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/apis/kubeletconfig/validation:go_default_library", - "//pkg/proxy/apis/kubeproxyconfig:go_default_library", - "//pkg/proxy/apis/kubeproxyconfig/validation:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library", @@ -31,7 +28,6 @@ go_test( embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//pkg/kubelet/apis/kubeletconfig:go_default_library", "//pkg/proxy/apis/kubeproxyconfig:go_default_library", "//pkg/util/pointer:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/cmd/kubeadm/app/cmd/upgrade/BUILD b/cmd/kubeadm/app/cmd/upgrade/BUILD index eaeb1289b78..9050ce1d37e 100644 --- a/cmd/kubeadm/app/cmd/upgrade/BUILD +++ b/cmd/kubeadm/app/cmd/upgrade/BUILD @@ -14,7 +14,6 @@ go_library( visibility = ["//visibility:public"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha3:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", "//cmd/kubeadm/app/cmd/util:go_default_library", diff --git a/cmd/kubeadm/app/componentconfigs/BUILD b/cmd/kubeadm/app/componentconfigs/BUILD new file mode 100644 index 00000000000..070f69733ea --- /dev/null +++ b/cmd/kubeadm/app/componentconfigs/BUILD @@ -0,0 +1,59 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "defaults.go", + "registrations.go", + "scheme.go", + "validation.go", + ], + importpath = "k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs", + visibility = ["//visibility:public"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha3:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", + "//cmd/kubeadm/app/util:go_default_library", + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", + "//pkg/kubelet/apis/kubeletconfig/validation:go_default_library", + "//pkg/proxy/apis/kubeproxyconfig:go_default_library", + "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", + "//pkg/proxy/apis/kubeproxyconfig/validation:go_default_library", + "//pkg/util/pointer:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = ["validation_test.go"], + embed = [":go_default_library"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//pkg/kubelet/apis/kubeletconfig:go_default_library", + "//pkg/proxy/apis/kubeproxyconfig:go_default_library", + "//pkg/util/pointer:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + ], +) diff --git a/cmd/kubeadm/app/phases/addons/proxy/BUILD b/cmd/kubeadm/app/phases/addons/proxy/BUILD index 76b5b7c6a0f..2fee37922a4 100644 --- a/cmd/kubeadm/app/phases/addons/proxy/BUILD +++ b/cmd/kubeadm/app/phases/addons/proxy/BUILD @@ -15,7 +15,7 @@ go_test( "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/config:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", + "//pkg/proxy/apis/kubeproxyconfig:go_default_library", "//pkg/util/pointer:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -34,11 +34,10 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy", deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/componentconfigs:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library", - "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/rbac/v1:go_default_library", diff --git a/cmd/kubeadm/app/phases/kubelet/BUILD b/cmd/kubeadm/app/phases/kubelet/BUILD index 512aacee02c..f6c8c9130a1 100644 --- a/cmd/kubeadm/app/phases/kubelet/BUILD +++ b/cmd/kubeadm/app/phases/kubelet/BUILD @@ -13,14 +13,13 @@ go_library( deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha3:go_default_library", + "//cmd/kubeadm/app/componentconfigs:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", "//pkg/apis/rbac/v1:go_default_library", "//pkg/kubelet/apis/kubeletconfig:go_default_library", - "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", - "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", "//pkg/util/initsystem:go_default_library", "//pkg/util/node:go_default_library", "//pkg/util/procfs:go_default_library", diff --git a/cmd/kubeadm/app/phases/uploadconfig/BUILD b/cmd/kubeadm/app/phases/uploadconfig/BUILD index 9963626318d..2aa89ed7cd7 100644 --- a/cmd/kubeadm/app/phases/uploadconfig/BUILD +++ b/cmd/kubeadm/app/phases/uploadconfig/BUILD @@ -12,11 +12,9 @@ go_library( importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig", deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/v1alpha3:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", - "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", + "//cmd/kubeadm/app/util/config:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", diff --git a/cmd/kubeadm/app/util/BUILD b/cmd/kubeadm/app/util/BUILD index 93c51705859..dc58000ff61 100644 --- a/cmd/kubeadm/app/util/BUILD +++ b/cmd/kubeadm/app/util/BUILD @@ -49,12 +49,13 @@ go_test( embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha3:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", ], ) diff --git a/cmd/kubeadm/app/util/config/BUILD b/cmd/kubeadm/app/util/config/BUILD index 5a9f4a35966..aa2d49a672d 100644 --- a/cmd/kubeadm/app/util/config/BUILD +++ b/cmd/kubeadm/app/util/config/BUILD @@ -20,6 +20,7 @@ go_library( "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha3:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", + "//cmd/kubeadm/app/componentconfigs:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//pkg/util/node:go_default_library", @@ -28,6 +29,7 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/tools/bootstrap/token/util:go_default_library",