...

Source file src/k8s.io/kubernetes/cmd/kubeadm/app/util/config/upgradeconfiguration.go

Documentation: k8s.io/kubernetes/cmd/kubeadm/app/util/config

     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  }
   183  

View as plain text