mirror of https://github.com/k3s-io/k3s
Merge pull request #73701 from rosti/refactor-initcfg-apis
kubeadm: Refactor InitConfiguration init APIspull/564/head
commit
1e6afac07c
|
@ -135,7 +135,7 @@ func addFlags(cmd *cobra.Command, cfg *renewConfig) {
|
|||
|
||||
func generateRenewalFunction(cert *certsphase.KubeadmCert, caCert *certsphase.KubeadmCert, cfg *renewConfig) func() {
|
||||
return func() {
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfg.cfgPath, &cfg.cfg)
|
||||
internalcfg, err := configutil.LoadOrDefaultInitConfiguration(cfg.cfgPath, &cfg.cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
if cfg.useCSR {
|
||||
|
|
|
@ -79,8 +79,8 @@ func newCmdUserKubeConfig(out io.Writer) *cobra.Command {
|
|||
kubeadmutil.CheckErr(errors.New("missing required argument --client-name"))
|
||||
}
|
||||
|
||||
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig("", cfg)
|
||||
// This call returns the ready-to-use configuration based on the default cfg populated by flags
|
||||
internalcfg, err := configutil.DefaultedInitConfiguration(cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// if the kubeconfig file for an additional user has to use a token, use it
|
||||
|
|
|
@ -124,11 +124,11 @@ func getSelfhostingSubCommand(in io.Reader) *cobra.Command {
|
|||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
|
||||
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
|
||||
// of the version from the internet when executing LoadOrDefaultInitConfiguration
|
||||
phases.SetKubernetesVersion(&cfg.ClusterConfiguration)
|
||||
|
||||
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
|
||||
internalcfg, err := configutil.LoadOrDefaultInitConfiguration(cfgPath, cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Converts the Static Pod-hosted control plane into a self-hosted one
|
||||
|
|
|
@ -178,7 +178,7 @@ func getSupportedComponentConfigAPIObjects() []string {
|
|||
}
|
||||
|
||||
func getDefaultedInitConfig() (*kubeadmapi.InitConfiguration, error) {
|
||||
return configutil.ConfigFileAndDefaultsToInternalConfig("", &kubeadmapiv1beta1.InitConfiguration{
|
||||
return configutil.DefaultedInitConfiguration(&kubeadmapiv1beta1.InitConfiguration{
|
||||
// TODO: Probably move to getDefaultedClusterConfig?
|
||||
LocalAPIEndpoint: kubeadmapiv1beta1.APIEndpoint{AdvertiseAddress: "1.2.3.4"},
|
||||
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
|
||||
|
@ -320,12 +320,13 @@ func NewCmdConfigUploadFromFile(out io.Writer, kubeConfigFile *string) *cobra.Co
|
|||
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// The default configuration is empty; everything should come from the file on disk
|
||||
klog.V(1).Infoln("[config] creating empty default configuration")
|
||||
defaultcfg := &kubeadmapiv1beta1.InitConfiguration{}
|
||||
// Upload the configuration using the file; don't care about the defaultcfg really
|
||||
// Default both statically and dynamically, convert to internal API type, and validate everything
|
||||
internalcfg, err := configutil.LoadInitConfigurationFromFile(cfgPath)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Upload the configuration using the file
|
||||
klog.V(1).Infof("[config] uploading configuration")
|
||||
err = uploadConfiguration(client, cfgPath, defaultcfg)
|
||||
err = uploadconfig.UploadConfiguration(internalcfg, client)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
@ -360,10 +361,18 @@ func NewCmdConfigUploadFromFlags(out io.Writer, kubeConfigFile *string) *cobra.C
|
|||
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
|
||||
// of the version from the internet when executing DefaultedInitConfiguration
|
||||
phaseutil.SetKubernetesVersion(&cfg.ClusterConfiguration)
|
||||
|
||||
// Default both statically and dynamically, convert to internal API type, and validate everything
|
||||
// The cfgPath argument is unset here as we shouldn't load a config file from disk, just go with cfg
|
||||
klog.V(1).Infoln("[config] converting to internal API type")
|
||||
internalcfg, err := configutil.DefaultedInitConfiguration(cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Finally, upload the configuration
|
||||
klog.V(1).Infof("[config] uploading configuration")
|
||||
err = uploadConfiguration(client, "", cfg)
|
||||
err = uploadconfig.UploadConfiguration(internalcfg, client)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
@ -384,24 +393,6 @@ func RunConfigView(out io.Writer, client clientset.Interface) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// uploadConfiguration handles the uploading of the configuration internally
|
||||
func uploadConfiguration(client clientset.Interface, cfgPath string, defaultcfg *kubeadmapiv1beta1.InitConfiguration) error {
|
||||
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
|
||||
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
|
||||
phaseutil.SetKubernetesVersion(&defaultcfg.ClusterConfiguration)
|
||||
|
||||
// Default both statically and dynamically, convert to internal API type, and validate everything
|
||||
// First argument is unset here as we shouldn't load a config file from disk
|
||||
klog.V(1).Infoln("[config] converting to internal API type")
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, defaultcfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Then just call the uploadconfig phase to do the rest of the work
|
||||
return uploadconfig.UploadConfiguration(internalcfg, client)
|
||||
}
|
||||
|
||||
// NewCmdConfigImages returns the "kubeadm config images" command
|
||||
func NewCmdConfigImages(out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
|
@ -427,7 +418,7 @@ func NewCmdConfigImagesPull() *cobra.Command {
|
|||
Run: func(_ *cobra.Command, _ []string) {
|
||||
externalcfg.ClusterConfiguration.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString)
|
||||
kubeadmutil.CheckErr(err)
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, externalcfg)
|
||||
internalcfg, err := configutil.LoadOrDefaultInitConfiguration(cfgPath, externalcfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
containerRuntime, err := utilruntime.NewContainerRuntime(utilsexec.New(), internalcfg.GetCRISocket())
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
@ -496,7 +487,7 @@ func NewCmdConfigImagesList(out io.Writer, mockK8sVersion *string) *cobra.Comman
|
|||
|
||||
// NewImagesList returns the underlying struct for the "kubeadm config images list" command
|
||||
func NewImagesList(cfgPath string, cfg *kubeadmapiv1beta1.InitConfiguration) (*ImagesList, error) {
|
||||
initcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
|
||||
initcfg, err := configutil.LoadOrDefaultInitConfiguration(cfgPath, cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert cfg to an internal cfg")
|
||||
}
|
||||
|
|
|
@ -275,7 +275,7 @@ func TestMigrate(t *testing.T) {
|
|||
t.Fatalf("failed to set new-config flag")
|
||||
}
|
||||
command.Run(nil, nil)
|
||||
if _, err := configutil.ConfigFileAndDefaultsToInternalConfig(newConfigPath, &kubeadmapiv1beta1.InitConfiguration{}); err != nil {
|
||||
if _, err := configutil.LoadInitConfigurationFromFile(newConfigPath); err != nil {
|
||||
t.Fatalf("Could not read output back into internal type: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -302,7 +302,7 @@ func newInitData(cmd *cobra.Command, args []string, options *initOptions, out io
|
|||
|
||||
// Either use the config file if specified, or convert public kubeadm API to the internal InitConfiguration
|
||||
// and validates InitConfiguration
|
||||
cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(options.cfgPath, options.externalcfg)
|
||||
cfg, err := configutil.LoadOrDefaultInitConfiguration(options.cfgPath, options.externalcfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -530,7 +530,7 @@ func fetchInitConfiguration(tlsBootstrapCfg *clientcmdapi.Config) (*kubeadmapi.I
|
|||
}
|
||||
|
||||
// Fetches the init configuration
|
||||
initConfiguration, err := configutil.FetchConfigFromFileOrCluster(tlsClient, os.Stdout, "join", "", true)
|
||||
initConfiguration, err := configutil.FetchInitConfigurationFromCluster(tlsClient, os.Stdout, "join", true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap")
|
||||
}
|
||||
|
|
|
@ -208,7 +208,7 @@ func getEtcdDataDir(manifestPath string, client clientset.Interface) (string, er
|
|||
var dataDir string
|
||||
|
||||
if client != nil {
|
||||
cfg, err := configutil.FetchConfigFromFileOrCluster(client, os.Stdout, "reset", "", false)
|
||||
cfg, err := configutil.FetchInitConfigurationFromCluster(client, os.Stdout, "reset", false)
|
||||
if err == nil && cfg.Etcd.Local != nil {
|
||||
return cfg.Etcd.Local.DataDir, nil
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ func resetConfigDir(configPathDir, pkiPathDir string) {
|
|||
|
||||
func resetDetectCRISocket(client clientset.Interface) (string, error) {
|
||||
// first try to connect to the cluster for the CRI socket
|
||||
cfg, err := configutil.FetchConfigFromFileOrCluster(client, os.Stdout, "reset", "", false)
|
||||
cfg, err := configutil.FetchInitConfigurationFromCluster(client, os.Stdout, "reset", false)
|
||||
if err == nil {
|
||||
return cfg.NodeRegistration.CRISocket, nil
|
||||
}
|
||||
|
|
|
@ -211,12 +211,12 @@ func NewCmdTokenGenerate(out io.Writer) *cobra.Command {
|
|||
// RunCreateToken generates a new bootstrap token and stores it as a secret on the server.
|
||||
func RunCreateToken(out io.Writer, client clientset.Interface, cfgPath string, cfg *kubeadmapiv1beta1.InitConfiguration, printJoinCommand bool, kubeConfigFile string) error {
|
||||
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
|
||||
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
|
||||
// of the version from the internet when executing LoadOrDefaultInitConfiguration
|
||||
phaseutil.SetKubernetesVersion(&cfg.ClusterConfiguration)
|
||||
|
||||
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
|
||||
klog.V(1).Infoln("[token] loading configurations")
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
|
||||
internalcfg, err := configutil.LoadOrDefaultInitConfiguration(cfgPath, cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ func TestRunCreateToken(t *testing.T) {
|
|||
cfg := &kubeadmapiv1beta1.InitConfiguration{
|
||||
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
|
||||
// KubernetesVersion is not used, but we set this explicitly to avoid
|
||||
// the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
|
||||
// the lookup of the version from the internet when executing LoadOrDefaultInitConfiguration
|
||||
KubernetesVersion: constants.MinimumControlPlaneVersion.String(),
|
||||
},
|
||||
BootstrapTokens: []kubeadmapiv1beta1.BootstrapToken{
|
||||
|
|
|
@ -14,7 +14,6 @@ go_library(
|
|||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/options:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/util:go_default_library",
|
||||
|
|
|
@ -27,7 +27,6 @@ import (
|
|||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
|
@ -90,9 +89,8 @@ func NewCmdApply(apf *applyPlanFlags) *cobra.Command {
|
|||
|
||||
// If the version is specified in config file, pick up that value.
|
||||
if flags.cfgPath != "" {
|
||||
klog.V(1).Infof("fetching configuration from file %s", flags.cfgPath)
|
||||
// Note that cfg isn't preserved here, it's just an one-off to populate flags.newK8sVersionStr based on --config
|
||||
cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(flags.cfgPath, &kubeadmapiv1beta1.InitConfiguration{})
|
||||
cfg, err := configutil.LoadInitConfigurationFromFile(flags.cfgPath)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
if cfg.KubernetesVersion != "" {
|
||||
|
|
|
@ -71,7 +71,14 @@ func enforceRequirements(flags *applyPlanFlags, dryRun bool, newK8sVersion strin
|
|||
|
||||
// Fetch the configuration from a file or ConfigMap and validate it
|
||||
fmt.Println("[upgrade/config] Making sure the configuration is correct:")
|
||||
cfg, err := configutil.FetchConfigFromFileOrCluster(client, os.Stdout, "upgrade/config", flags.cfgPath, false)
|
||||
|
||||
var cfg *kubeadmapi.InitConfiguration
|
||||
if flags.cfgPath != "" {
|
||||
cfg, err = configutil.LoadInitConfigurationFromFile(flags.cfgPath)
|
||||
} else {
|
||||
cfg, err = configutil.FetchInitConfigurationFromCluster(client, os.Stdout, "upgrade/config", false)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
fmt.Printf("[upgrade/config] In order to upgrade, a ConfigMap called %q in the %s namespace must exist.\n", constants.KubeadmConfigConfigMap, metav1.NamespaceSystem)
|
||||
|
|
|
@ -26,7 +26,6 @@ import (
|
|||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
"k8s.io/klog"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
|
@ -78,8 +77,7 @@ func NewCmdDiff(out io.Writer) *cobra.Command {
|
|||
func runDiff(flags *diffFlags, args []string) error {
|
||||
|
||||
// If the version is specified in config file, pick up that value.
|
||||
klog.V(1).Infof("fetching configuration from file %s", flags.cfgPath)
|
||||
cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(flags.cfgPath, &kubeadmapiv1beta1.InitConfiguration{})
|
||||
cfg, err := configutil.LoadInitConfigurationFromFile(flags.cfgPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ func RunUpgradeControlPlane(flags *controlplaneUpgradeFlags) error {
|
|||
waiter := apiclient.NewKubeWaiter(client, upgrade.UpgradeManifestTimeout, os.Stdout)
|
||||
|
||||
// Fetches the cluster configuration
|
||||
cfg, err := configutil.FetchConfigFromFileOrCluster(client, os.Stdout, "upgrade", "", false)
|
||||
cfg, err := configutil.FetchInitConfigurationFromCluster(client, os.Stdout, "upgrade", false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap")
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/version"
|
||||
"k8s.io/klog"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
|
@ -62,8 +61,7 @@ func NewCmdPlan(apf *applyPlanFlags) *cobra.Command {
|
|||
|
||||
// If the version is specified in config file, pick up that value.
|
||||
if flags.cfgPath != "" {
|
||||
klog.V(1).Infof("fetching configuration from file %s", flags.cfgPath)
|
||||
cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(flags.cfgPath, &kubeadmapiv1beta1.InitConfiguration{})
|
||||
cfg, err := configutil.LoadInitConfigurationFromFile(flags.cfgPath)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
if cfg.KubernetesVersion != "" {
|
||||
|
|
|
@ -201,7 +201,7 @@ func TestEnsureProxyAddon(t *testing.T) {
|
|||
masterConfig.Networking.PodSubnet = "2001:101::/96"
|
||||
}
|
||||
|
||||
intMaster, err := configutil.ConfigFileAndDefaultsToInternalConfig("", masterConfig)
|
||||
intMaster, err := configutil.DefaultedInitConfiguration(masterConfig)
|
||||
if err != nil {
|
||||
t.Errorf("test failed to convert external to internal version")
|
||||
break
|
||||
|
|
|
@ -84,7 +84,7 @@ func TestUploadConfiguration(t *testing.T) {
|
|||
CRISocket: "/var/run/custom-cri.sock",
|
||||
},
|
||||
}
|
||||
cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig("", initialcfg)
|
||||
cfg, err := configutil.DefaultedInitConfiguration(initialcfg)
|
||||
|
||||
// cleans up component config to make cfg and decodedcfg comparable (now component config are not stored anymore in kubeadm-config config map)
|
||||
cfg.ComponentConfigs = kubeadmapi.ComponentConfigs{}
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"crypto/x509"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
|
@ -39,54 +38,26 @@ import (
|
|||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
)
|
||||
|
||||
// FetchConfigFromFileOrCluster fetches configuration required for upgrading your cluster from a file (which has precedence) or a ConfigMap in the cluster
|
||||
func FetchConfigFromFileOrCluster(client clientset.Interface, w io.Writer, logPrefix, cfgPath string, newControlPlane bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
// Load the configuration from a file or the cluster
|
||||
initcfg, err := loadConfiguration(client, w, logPrefix, cfgPath, newControlPlane)
|
||||
// FetchInitConfigurationFromCluster fetches configuration from a ConfigMap in the cluster
|
||||
func FetchInitConfigurationFromCluster(client clientset.Interface, w io.Writer, logPrefix string, newControlPlane bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
fmt.Fprintf(w, "[%s] Reading configuration from the cluster...\n", logPrefix)
|
||||
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.KubeadmConfigConfigMap)
|
||||
|
||||
// Fetch the actual config from cluster
|
||||
cfg, err := getInitConfigurationFromCluster(constants.KubernetesDir, client, newControlPlane)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Apply dynamic defaults
|
||||
if err := SetInitDynamicDefaults(initcfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return initcfg, err
|
||||
}
|
||||
|
||||
// loadConfiguration loads the configuration byte slice from either a file or the cluster ConfigMap
|
||||
func loadConfiguration(client clientset.Interface, w io.Writer, logPrefix, cfgPath string, newControlPlane bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
// The config file has the highest priority
|
||||
if cfgPath != "" {
|
||||
fmt.Fprintf(w, "[%s] Reading configuration options from a file: %s\n", logPrefix, cfgPath)
|
||||
return loadInitConfigurationFromFile(cfgPath)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "[%s] Reading configuration from the cluster...\n", logPrefix)
|
||||
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.KubeadmConfigConfigMap)
|
||||
return getInitConfigurationFromCluster(constants.KubernetesDir, client, newControlPlane)
|
||||
}
|
||||
|
||||
func loadInitConfigurationFromFile(cfgPath string) (*kubeadmapi.InitConfiguration, error) {
|
||||
configBytes, err := ioutil.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
if err := SetInitDynamicDefaults(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal the versioned configuration populated from the file,
|
||||
// convert it to the internal API types, then default and validate
|
||||
// NB the file contains multiple YAML, with a combination of
|
||||
// - a YAML with a InitConfiguration object
|
||||
// - a YAML with a ClusterConfiguration object (without embedded component configs)
|
||||
// - separated YAML for components configs
|
||||
initcfg, err := BytesToInternalConfig(configBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return initcfg, nil
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// getInitConfigurationFromCluster is separate only for testing purposes, don't call it directly, use FetchInitConfigurationFromCluster instead
|
||||
func getInitConfigurationFromCluster(kubeconfigDir string, client clientset.Interface, newControlPlane bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
// TODO: This code should support reading the MasterConfiguration key as well for backwards-compat
|
||||
// Also, the config map really should be KubeadmConfigConfigMap...
|
||||
|
@ -124,7 +95,6 @@ func getInitConfigurationFromCluster(kubeconfigDir string, client clientset.Inte
|
|||
return nil, errors.Wrap(err, "failed to getAPIEndpoint")
|
||||
}
|
||||
}
|
||||
|
||||
return initcfg, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -172,76 +171,6 @@ G+2/lm8TaVjoU7Fi5Ka5G5HY2GLaR7P+IxYcrMHCl62Y7Rqcrnc=
|
|||
`),
|
||||
}
|
||||
|
||||
func TestLoadInitConfigurationFromFile(t *testing.T) {
|
||||
// Create temp folder for the test case
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create tmpdir")
|
||||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
fileContents []byte
|
||||
}{
|
||||
{
|
||||
name: "v1beta1.partial1",
|
||||
fileContents: cfgFiles["InitConfiguration_v1beta1"],
|
||||
},
|
||||
{
|
||||
name: "v1beta1.partial2",
|
||||
fileContents: cfgFiles["ClusterConfiguration_v1beta1"],
|
||||
},
|
||||
{
|
||||
name: "v1beta1.full",
|
||||
fileContents: bytes.Join([][]byte{
|
||||
cfgFiles["InitConfiguration_v1beta1"],
|
||||
cfgFiles["ClusterConfiguration_v1beta1"],
|
||||
cfgFiles["Kube-proxy_componentconfig"],
|
||||
cfgFiles["Kubelet_componentconfig"],
|
||||
}, []byte(kubeadmconstants.YAMLDocumentSeparator)),
|
||||
},
|
||||
{
|
||||
name: "v1alpha3.partial1",
|
||||
fileContents: cfgFiles["InitConfiguration_v1alpha3"],
|
||||
},
|
||||
{
|
||||
name: "v1alpha3.partial2",
|
||||
fileContents: cfgFiles["ClusterConfiguration_v1alpha3"],
|
||||
},
|
||||
{
|
||||
name: "v1alpha3.full",
|
||||
fileContents: bytes.Join([][]byte{
|
||||
cfgFiles["InitConfiguration_v1alpha3"],
|
||||
cfgFiles["ClusterConfiguration_v1alpha3"],
|
||||
cfgFiles["Kube-proxy_componentconfig"],
|
||||
cfgFiles["Kubelet_componentconfig"],
|
||||
}, []byte(kubeadmconstants.YAMLDocumentSeparator)),
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t2 *testing.T) {
|
||||
cfgPath := filepath.Join(tmpdir, rt.name)
|
||||
err := ioutil.WriteFile(cfgPath, rt.fileContents, 0644)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create file")
|
||||
return
|
||||
}
|
||||
|
||||
obj, err := loadInitConfigurationFromFile(cfgPath)
|
||||
if err != nil {
|
||||
t.Errorf("Error reading file: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if obj == nil {
|
||||
t.Errorf("Unexpected nil return value")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNodeNameFromKubeletConfig(t *testing.T) {
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
|
|
|
@ -154,7 +154,7 @@ func MigrateOldConfigFromFile(cfgPath string) ([]byte, error) {
|
|||
|
||||
// Migrate InitConfiguration and ClusterConfiguration if there are any in the config
|
||||
if kubeadmutil.GroupVersionKindsHasInitConfiguration(gvks...) || kubeadmutil.GroupVersionKindsHasClusterConfiguration(gvks...) {
|
||||
o, err := ConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1beta1.InitConfiguration{})
|
||||
o, err := LoadInitConfigurationFromFile(cfgPath)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
|
|
@ -161,32 +161,38 @@ func SetClusterDynamicDefaults(cfg *kubeadmapi.ClusterConfiguration, advertiseAd
|
|||
return nil
|
||||
}
|
||||
|
||||
// ConfigFileAndDefaultsToInternalConfig takes a path to a config file and a versioned configuration that can serve as the default config
|
||||
// If cfgPath is specified, defaultversionedcfg will always get overridden. Otherwise, the default config (often populated by flags) will be used.
|
||||
// Then the external, versioned configuration is defaulted and converted to the internal type.
|
||||
// Right thereafter, the configuration is defaulted again with dynamic values (like IP addresses of a machine, etc)
|
||||
// Lastly, the internal config is validated and returned.
|
||||
func ConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *kubeadmapiv1beta1.InitConfiguration) (*kubeadmapi.InitConfiguration, error) {
|
||||
// DefaultedInitConfiguration takes a versioned init config (often populated by flags), defaults it and converts it into internal InitConfiguration
|
||||
func DefaultedInitConfiguration(defaultversionedcfg *kubeadmapiv1beta1.InitConfiguration) (*kubeadmapi.InitConfiguration, error) {
|
||||
internalcfg := &kubeadmapi.InitConfiguration{}
|
||||
|
||||
if cfgPath != "" {
|
||||
// Loads configuration from config file, if provided
|
||||
// Nb. --config overrides command line flags
|
||||
klog.V(1).Infoln("loading configuration from the given file")
|
||||
// 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)
|
||||
|
||||
b, err := ioutil.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to read config from %q ", cfgPath)
|
||||
}
|
||||
internalcfg, err = BytesToInternalConfig(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// 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)
|
||||
// Applies dynamic defaults to settings not provided with flags
|
||||
if err := SetInitDynamicDefaults(internalcfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Validates cfg (flags/configs + defaults + dynamic defaults)
|
||||
if err := validation.ValidateInitConfiguration(internalcfg).ToAggregate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return internalcfg, nil
|
||||
}
|
||||
|
||||
// LoadInitConfigurationFromFile loads a supported versioned InitConfiguration from a file, converts it into internal config, defaults it and verifies it.
|
||||
func LoadInitConfigurationFromFile(cfgPath string) (*kubeadmapi.InitConfiguration, error) {
|
||||
klog.V(1).Infof("loading configuration from %q", cfgPath)
|
||||
|
||||
b, err := ioutil.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to read config from %q ", cfgPath)
|
||||
}
|
||||
|
||||
internalcfg, err := BytesToInternalConfig(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Applies dynamic defaults to settings not provided with flags
|
||||
|
@ -200,6 +206,21 @@ func ConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *
|
|||
return internalcfg, nil
|
||||
}
|
||||
|
||||
// LoadOrDefaultInitConfiguration takes a path to a config file and a versioned configuration that can serve as the default config
|
||||
// If cfgPath is specified, defaultversionedcfg will always get overridden. Otherwise, the default config (often populated by flags) will be used.
|
||||
// Then the external, versioned configuration is defaulted and converted to the internal type.
|
||||
// Right thereafter, the configuration is defaulted again with dynamic values (like IP addresses of a machine, etc)
|
||||
// Lastly, the internal config is validated and returned.
|
||||
func LoadOrDefaultInitConfiguration(cfgPath string, defaultversionedcfg *kubeadmapiv1beta1.InitConfiguration) (*kubeadmapi.InitConfiguration, error) {
|
||||
if cfgPath != "" {
|
||||
// Loads configuration from config file, if provided
|
||||
// Nb. --config overrides command line flags
|
||||
return LoadInitConfigurationFromFile(cfgPath)
|
||||
}
|
||||
|
||||
return DefaultedInitConfiguration(defaultversionedcfg)
|
||||
}
|
||||
|
||||
// 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 InitConfiguration struct
|
||||
|
|
|
@ -19,6 +19,8 @@ package config
|
|||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
|
@ -27,6 +29,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -51,13 +54,84 @@ func diff(expected, actual []byte) string {
|
|||
return diffBytes.String()
|
||||
}
|
||||
|
||||
func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) {
|
||||
func TestLoadInitConfigurationFromFile(t *testing.T) {
|
||||
// Create temp folder for the test case
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create tmpdir")
|
||||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
// cfgFiles is in cluster_test.go
|
||||
var tests = []struct {
|
||||
name string
|
||||
fileContents []byte
|
||||
}{
|
||||
{
|
||||
name: "v1beta1.partial1",
|
||||
fileContents: cfgFiles["InitConfiguration_v1beta1"],
|
||||
},
|
||||
{
|
||||
name: "v1beta1.partial2",
|
||||
fileContents: cfgFiles["ClusterConfiguration_v1beta1"],
|
||||
},
|
||||
{
|
||||
name: "v1beta1.full",
|
||||
fileContents: bytes.Join([][]byte{
|
||||
cfgFiles["InitConfiguration_v1beta1"],
|
||||
cfgFiles["ClusterConfiguration_v1beta1"],
|
||||
cfgFiles["Kube-proxy_componentconfig"],
|
||||
cfgFiles["Kubelet_componentconfig"],
|
||||
}, []byte(constants.YAMLDocumentSeparator)),
|
||||
},
|
||||
{
|
||||
name: "v1alpha3.partial1",
|
||||
fileContents: cfgFiles["InitConfiguration_v1alpha3"],
|
||||
},
|
||||
{
|
||||
name: "v1alpha3.partial2",
|
||||
fileContents: cfgFiles["ClusterConfiguration_v1alpha3"],
|
||||
},
|
||||
{
|
||||
name: "v1alpha3.full",
|
||||
fileContents: bytes.Join([][]byte{
|
||||
cfgFiles["InitConfiguration_v1alpha3"],
|
||||
cfgFiles["ClusterConfiguration_v1alpha3"],
|
||||
cfgFiles["Kube-proxy_componentconfig"],
|
||||
cfgFiles["Kubelet_componentconfig"],
|
||||
}, []byte(constants.YAMLDocumentSeparator)),
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t2 *testing.T) {
|
||||
cfgPath := filepath.Join(tmpdir, rt.name)
|
||||
err := ioutil.WriteFile(cfgPath, rt.fileContents, 0644)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create file")
|
||||
return
|
||||
}
|
||||
|
||||
obj, err := LoadInitConfigurationFromFile(cfgPath)
|
||||
if err != nil {
|
||||
t.Errorf("Error reading file: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if obj == nil {
|
||||
t.Errorf("Unexpected nil return value")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitConfigurationMarshallingFromFile(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name, in, out string
|
||||
groupVersion schema.GroupVersion
|
||||
expectedErr bool
|
||||
}{
|
||||
// These tests are reading one file, loading it using ConfigFileAndDefaultsToInternalConfig that all of kubeadm is using for unmarshal of our API types,
|
||||
// These tests are reading one file, loading it using LoadInitConfigurationFromFile that all of kubeadm is using for unmarshal of our API types,
|
||||
// and then marshals the internal object to the expected groupVersion
|
||||
{ // v1alpha3 -> internal
|
||||
name: "v1alpha3ToInternal",
|
||||
|
@ -83,7 +157,7 @@ func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) {
|
|||
out: master_v1beta1YAML,
|
||||
groupVersion: kubeadmapiv1beta1.SchemeGroupVersion,
|
||||
},
|
||||
// These tests are reading one file that has only a subset of the fields populated, loading it using ConfigFileAndDefaultsToInternalConfig,
|
||||
// These tests are reading one file that has only a subset of the fields populated, loading it using LoadInitConfigurationFromFile,
|
||||
// and then marshals the internal object to the expected groupVersion
|
||||
{ // v1beta1 -> default -> validate -> internal -> v1beta1
|
||||
name: "incompleteYAMLToDefaultedv1beta1",
|
||||
|
@ -101,7 +175,7 @@ func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) {
|
|||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t2 *testing.T) {
|
||||
|
||||
internalcfg, err := ConfigFileAndDefaultsToInternalConfig(rt.in, &kubeadmapiv1beta1.InitConfiguration{})
|
||||
internalcfg, err := LoadInitConfigurationFromFile(rt.in)
|
||||
if err != nil {
|
||||
if rt.expectedErr {
|
||||
return
|
||||
|
|
|
@ -157,7 +157,7 @@ func AssertError(t *testing.T, err error, expected string) {
|
|||
|
||||
// GetDefaultInternalConfig returns a defaulted kubeadmapi.InitConfiguration
|
||||
func GetDefaultInternalConfig(t *testing.T) *kubeadmapi.InitConfiguration {
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig("", &kubeadmapiv1beta1.InitConfiguration{})
|
||||
internalcfg, err := configutil.DefaultedInitConfiguration(&kubeadmapiv1beta1.InitConfiguration{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting default config: %v", err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue