k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/cmd/kubeadm/app/util/config/upgradeconfiguration.go (about) 1 /* 2 Copyright 2024 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package config 18 19 import ( 20 "os" 21 22 "github.com/pkg/errors" 23 24 "k8s.io/apimachinery/pkg/runtime" 25 "k8s.io/apimachinery/pkg/util/sets" 26 "k8s.io/klog/v2" 27 kubeproxyconfig "k8s.io/kube-proxy/config/v1alpha1" 28 kubeletconfig "k8s.io/kubelet/config/v1beta1" 29 30 kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" 31 kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" 32 kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta4" 33 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" 34 "k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs" 35 kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" 36 "k8s.io/kubernetes/cmd/kubeadm/app/util/config/strict" 37 ) 38 39 var componentCfgGV = sets.New(kubeproxyconfig.GroupName, kubeletconfig.GroupName) 40 41 // documentMapToUpgradeConfiguration takes a map between GVKs and YAML documents (as returned by SplitYAMLDocuments), 42 // finds a UpgradeConfiguration, decodes it, dynamically defaults it and then validates it prior to return. 43 func documentMapToUpgradeConfiguration(gvkmap kubeadmapi.DocumentMap, allowDeprecated bool) (*kubeadmapi.UpgradeConfiguration, error) { 44 var internalcfg *kubeadmapi.UpgradeConfiguration 45 46 for gvk, bytes := range gvkmap { 47 // check if this version is supported and possibly not deprecated 48 if err := validateSupportedVersion(gvk.GroupVersion(), allowDeprecated, true); err != nil { 49 return nil, err 50 } 51 52 // verify the validity of the YAML 53 if err := strict.VerifyUnmarshalStrict([]*runtime.Scheme{kubeadmscheme.Scheme}, gvk, bytes); err != nil { 54 klog.Warning(err.Error()) 55 } 56 57 if kubeadmutil.GroupVersionKindsHasInitConfiguration(gvk) || kubeadmutil.GroupVersionKindsHasClusterConfiguration(gvk) { 58 klog.Warningf("[config] WARNING: YAML document with GroupVersionKind %v is deprecated for upgrade, please use config file with kind of UpgradeConfiguration instead \n", gvk) 59 continue 60 } 61 62 if kubeadmutil.GroupVersionKindsHasUpgradeConfiguration(gvk) { 63 // Set internalcfg to an empty struct value the deserializer will populate 64 internalcfg = &kubeadmapi.UpgradeConfiguration{} 65 // Decode the bytes into the internal struct. Under the hood, the bytes will be unmarshalled into the 66 // right external version, defaulted, and converted into the internal version. 67 if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), bytes, internalcfg); err != nil { 68 return nil, err 69 } 70 continue 71 } 72 73 // If the group is neither a kubeadm core type or of a supported component config group, we dump a warning about it being ignored 74 if !componentconfigs.Scheme.IsGroupRegistered(gvk.Group) { 75 klog.Warningf("[config] WARNING: Ignored YAML document with GroupVersionKind %v\n", gvk) 76 } 77 } 78 79 // If UpgradeConfiguration wasn't given, default it by creating an external struct instance, default it and convert into the internal type 80 if internalcfg == nil { 81 extinitcfg := &kubeadmapiv1.UpgradeConfiguration{} 82 kubeadmscheme.Scheme.Default(extinitcfg) 83 // Set upgradeCfg to an empty struct value the deserializer will populate 84 internalcfg = &kubeadmapi.UpgradeConfiguration{} 85 if err := kubeadmscheme.Scheme.Convert(extinitcfg, internalcfg, nil); err != nil { 86 return nil, err 87 } 88 } 89 90 // Validates cfg 91 if err := validation.ValidateUpgradeConfiguration(internalcfg).ToAggregate(); err != nil { 92 return nil, err 93 } 94 95 return internalcfg, nil 96 } 97 98 // DocMapToUpgradeConfiguration converts documentMap to an internal, defaulted and validated UpgradeConfiguration object. 99 // The map may contain many different YAML documents. These YAML documents are parsed one-by-one 100 // and well-known ComponentConfig GroupVersionKinds are stored inside of the internal UpgradeConfiguration struct. 101 // The resulting UpgradeConfiguration is then dynamically defaulted and validated prior to return. 102 func DocMapToUpgradeConfiguration(gvkmap kubeadmapi.DocumentMap) (*kubeadmapi.UpgradeConfiguration, error) { 103 return documentMapToUpgradeConfiguration(gvkmap, false) 104 } 105 106 // LoadUpgradeConfigurationFromFile loads UpgradeConfiguration from a file. 107 func LoadUpgradeConfigurationFromFile(cfgPath string, _ LoadOrDefaultConfigurationOptions) (*kubeadmapi.UpgradeConfiguration, error) { 108 var err error 109 var upgradeCfg *kubeadmapi.UpgradeConfiguration 110 111 // Otherwise, we have a config file. Let's load it. 112 configBytes, err := os.ReadFile(cfgPath) 113 if err != nil { 114 return nil, errors.Wrapf(err, "unable to load config from file %q", cfgPath) 115 } 116 117 // Split the YAML documents in the file into a DocumentMap 118 docmap, err := kubeadmutil.SplitYAMLDocuments(configBytes) 119 if err != nil { 120 return nil, err 121 } 122 123 // Convert documentMap to internal UpgradeConfiguration, InitConfiguration and ClusterConfiguration from config file will be ignored. 124 // Upgrade should respect the cluster configuration from the existing cluster, re-configure the cluster with a InitConfiguration and 125 // ClusterConfiguration from the config file is not allowed for upgrade. 126 if isKubeadmConfigPresent(docmap) { 127 if upgradeCfg, err = DocMapToUpgradeConfiguration(docmap); err != nil { 128 return nil, err 129 } 130 } 131 132 // Check is there any component configs defined in the config file. 133 for gvk := range docmap { 134 if componentCfgGV.Has(gvk.Group) { 135 klog.Warningf("[config] WARNING: YAML document with Component Configs %v is deprecated for upgrade and will be ignored \n", gvk.Group) 136 continue 137 } 138 } 139 140 return upgradeCfg, nil 141 } 142 143 // LoadOrDefaultUpgradeConfiguration takes a path to a config file and a versioned configuration that can serve as the default config 144 // If cfgPath is specified, defaultversionedcfg will always get overridden. Otherwise, the default config (often populated by flags) will be used. 145 // Then the external, versioned configuration is defaulted and converted to the internal type. 146 // Right thereafter, the configuration is defaulted again with dynamic values 147 // Lastly, the internal config is validated and returned. 148 func LoadOrDefaultUpgradeConfiguration(cfgPath string, defaultversionedcfg *kubeadmapiv1.UpgradeConfiguration, opts LoadOrDefaultConfigurationOptions) (*kubeadmapi.UpgradeConfiguration, error) { 149 var ( 150 config *kubeadmapi.UpgradeConfiguration 151 err error 152 ) 153 if cfgPath != "" { 154 // Loads configuration from config file, if provided 155 config, err = LoadUpgradeConfigurationFromFile(cfgPath, opts) 156 } else { 157 config, err = DefaultedUpgradeConfiguration(defaultversionedcfg, opts) 158 } 159 if err == nil { 160 prepareStaticVariables(config) 161 } 162 return config, err 163 } 164 165 // DefaultedUpgradeConfiguration takes a versioned UpgradeConfiguration (usually filled in by command line parameters), defaults it, converts it to internal and validates it 166 func DefaultedUpgradeConfiguration(defaultversionedcfg *kubeadmapiv1.UpgradeConfiguration, _ LoadOrDefaultConfigurationOptions) (*kubeadmapi.UpgradeConfiguration, error) { 167 internalcfg := &kubeadmapi.UpgradeConfiguration{} 168 169 // Takes passed flags into account; the defaulting is executed once again enforcing assignment of 170 // static default values to cfg only for values not provided with flags 171 kubeadmscheme.Scheme.Default(defaultversionedcfg) 172 if err := kubeadmscheme.Scheme.Convert(defaultversionedcfg, internalcfg, nil); err != nil { 173 return nil, err 174 } 175 176 // Validates cfg 177 if err := validation.ValidateUpgradeConfiguration(internalcfg).ToAggregate(); err != nil { 178 return nil, err 179 } 180 181 return internalcfg, nil 182 }