From d9e48705ff66acd20a483e8bc9f14e91ab48876c Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov" Date: Sun, 31 Dec 2023 20:09:03 +0200 Subject: [PATCH] kubeadm: make the active timeouts structure accessible from anywhere Currently, timeouts are only accessible if a kubeadm runtime.Object{} like InitConfiguration is passed around. Any time a config is loaded or defaulted, store the Timeouts structure in a thread-safe way in the main kubeadm API package with SetActiveTimeouts(). Optionally, a deep-copy can be performed before calling SetActiveTimeouts(). Make this struct accessible with GetActiveTimeouts(). Ensure these functions are thread safe. On init() make sure the struct is defaulted, so that unit tests can work with these values. --- cmd/kubeadm/app/apis/kubeadm/timeoututils.go | 24 +++++++++++++++++++ cmd/kubeadm/app/util/config/common.go | 13 ++++++++++ .../app/util/config/initconfiguration.go | 19 ++++++++++----- .../app/util/config/joinconfiguration.go | 15 ++++++++---- .../app/util/config/resetconfiguration.go | 14 ++++++++--- 5 files changed, 72 insertions(+), 13 deletions(-) diff --git a/cmd/kubeadm/app/apis/kubeadm/timeoututils.go b/cmd/kubeadm/app/apis/kubeadm/timeoututils.go index 6f533d8cd58..7e88fb8300a 100644 --- a/cmd/kubeadm/app/apis/kubeadm/timeoututils.go +++ b/cmd/kubeadm/app/apis/kubeadm/timeoututils.go @@ -17,6 +17,7 @@ limitations under the License. package kubeadm import ( + "sync" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -33,3 +34,26 @@ func SetDefaultTimeouts(t **Timeouts) { Discovery: &metav1.Duration{Duration: 5 * time.Minute}, } } + +var ( + activeTimeouts *Timeouts = nil + timeoutMutex = &sync.RWMutex{} +) + +func init() { + SetDefaultTimeouts(&activeTimeouts) +} + +// GetActiveTimeouts gets the active timeouts structure. +func GetActiveTimeouts() *Timeouts { + timeoutMutex.RLock() + defer timeoutMutex.RUnlock() + return activeTimeouts +} + +// SetActiveTimeouts sets the active timeouts structure. +func SetActiveTimeouts(timeouts *Timeouts) { + timeoutMutex.Lock() + activeTimeouts = timeouts.DeepCopy() + timeoutMutex.Unlock() +} diff --git a/cmd/kubeadm/app/util/config/common.go b/cmd/kubeadm/app/util/config/common.go index 0aed1373444..36f445fe4c4 100644 --- a/cmd/kubeadm/app/util/config/common.go +++ b/cmd/kubeadm/app/util/config/common.go @@ -384,6 +384,19 @@ func isKubeadmPrereleaseVersion(versionInfo *apimachineryversion.Info, k8sVersio return false } +// prepareStaticVariables takes a given config and stores values from it in variables +// that can be used from multiple packages. +func prepareStaticVariables(config any) { + switch c := config.(type) { + case *kubeadmapi.InitConfiguration: + kubeadmapi.SetActiveTimeouts(c.Timeouts.DeepCopy()) + case *kubeadmapi.JoinConfiguration: + kubeadmapi.SetActiveTimeouts(c.Timeouts.DeepCopy()) + case *kubeadmapi.ResetConfiguration: + kubeadmapi.SetActiveTimeouts(c.Timeouts.DeepCopy()) + } +} + // migrateMutator can be used to mutate a slice of configuration objects. // The mutation is applied in-place and no copies are made. type migrateMutator struct { diff --git a/cmd/kubeadm/app/util/config/initconfiguration.go b/cmd/kubeadm/app/util/config/initconfiguration.go index 9ee852cd5f4..e5e4d1944e8 100644 --- a/cmd/kubeadm/app/util/config/initconfiguration.go +++ b/cmd/kubeadm/app/util/config/initconfiguration.go @@ -229,7 +229,7 @@ func DefaultedStaticInitConfiguration() (*kubeadmapi.InitConfiguration, error) { } // DefaultedInitConfiguration takes a versioned init config (often populated by flags), defaults it and converts it into internal InitConfiguration -func DefaultedInitConfiguration(versionedInitCfg *kubeadmapiv1.InitConfiguration, versionedClusterCfg *kubeadmapiv1.ClusterConfiguration, skipCRIDetect bool) (*kubeadmapi.InitConfiguration, error) { +func DefaultedInitConfiguration(versionedInitCfg *kubeadmapiv1.InitConfiguration, versionedClusterCfg *kubeadmapiv1.ClusterConfiguration, opts LoadOrDefaultConfigurationOptions) (*kubeadmapi.InitConfiguration, error) { internalcfg := &kubeadmapi.InitConfiguration{} // Takes passed flags into account; the defaulting is executed once again enforcing assignment of @@ -245,7 +245,7 @@ func DefaultedInitConfiguration(versionedInitCfg *kubeadmapiv1.InitConfiguration } // Applies dynamic defaults to settings not provided with flags - if err := SetInitDynamicDefaults(internalcfg, skipCRIDetect); err != nil { + if err := SetInitDynamicDefaults(internalcfg, opts.SkipCRIDetect); err != nil { return nil, err } // Validates cfg (flags/configs + defaults + dynamic defaults) @@ -273,13 +273,20 @@ func LoadInitConfigurationFromFile(cfgPath string, opts LoadOrDefaultConfigurati // 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, versionedInitCfg *kubeadmapiv1.InitConfiguration, versionedClusterCfg *kubeadmapiv1.ClusterConfiguration, opts LoadOrDefaultConfigurationOptions) (*kubeadmapi.InitConfiguration, error) { + var ( + config *kubeadmapi.InitConfiguration + err error + ) if cfgPath != "" { // Loads configuration from config file, if provided - // Nb. --config overrides command line flags - return LoadInitConfigurationFromFile(cfgPath, opts) + config, err = LoadInitConfigurationFromFile(cfgPath, opts) + } else { + config, err = DefaultedInitConfiguration(versionedInitCfg, versionedClusterCfg, opts) } - - return DefaultedInitConfiguration(versionedInitCfg, versionedClusterCfg, opts.SkipCRIDetect) + if err == nil { + prepareStaticVariables(config) + } + return config, err } // BytesToInitConfiguration converts a byte slice to an internal, defaulted and validated InitConfiguration object. diff --git a/cmd/kubeadm/app/util/config/joinconfiguration.go b/cmd/kubeadm/app/util/config/joinconfiguration.go index 09d5848fd61..df7160b1e5d 100644 --- a/cmd/kubeadm/app/util/config/joinconfiguration.go +++ b/cmd/kubeadm/app/util/config/joinconfiguration.go @@ -62,13 +62,20 @@ func SetJoinControlPlaneDefaults(cfg *kubeadmapi.JoinControlPlane) error { // 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 LoadOrDefaultJoinConfiguration(cfgPath string, defaultversionedcfg *kubeadmapiv1.JoinConfiguration, opts LoadOrDefaultConfigurationOptions) (*kubeadmapi.JoinConfiguration, error) { + var ( + config *kubeadmapi.JoinConfiguration + err error + ) if cfgPath != "" { // Loads configuration from config file, if provided - // Nb. --config overrides command line flags, TODO: fix this - return LoadJoinConfigurationFromFile(cfgPath, opts) + config, err = LoadJoinConfigurationFromFile(cfgPath, opts) + } else { + config, err = DefaultedJoinConfiguration(defaultversionedcfg, opts) } - - return DefaultedJoinConfiguration(defaultversionedcfg, opts) + if err == nil { + prepareStaticVariables(config) + } + return config, err } // LoadJoinConfigurationFromFile loads versioned JoinConfiguration from file, converts it to internal, defaults and validates it diff --git a/cmd/kubeadm/app/util/config/resetconfiguration.go b/cmd/kubeadm/app/util/config/resetconfiguration.go index 9335db9c264..63994ff1939 100644 --- a/cmd/kubeadm/app/util/config/resetconfiguration.go +++ b/cmd/kubeadm/app/util/config/resetconfiguration.go @@ -66,12 +66,20 @@ func SetResetDynamicDefaults(cfg *kubeadmapi.ResetConfiguration, skipCRIDetect b // Right thereafter, the configuration is defaulted again with dynamic values // Lastly, the internal config is validated and returned. func LoadOrDefaultResetConfiguration(cfgPath string, defaultversionedcfg *kubeadmapiv1.ResetConfiguration, opts LoadOrDefaultConfigurationOptions) (*kubeadmapi.ResetConfiguration, error) { + var ( + config *kubeadmapi.ResetConfiguration + err error + ) if cfgPath != "" { // Loads configuration from config file, if provided - return LoadResetConfigurationFromFile(cfgPath, opts) + config, err = LoadResetConfigurationFromFile(cfgPath, opts) + } else { + config, err = DefaultedResetConfiguration(defaultversionedcfg, opts) } - - return DefaultedResetConfiguration(defaultversionedcfg, opts) + if err == nil { + prepareStaticVariables(config) + } + return config, err } // LoadResetConfigurationFromFile loads versioned ResetConfiguration from file, converts it to internal, defaults and validates it