kubeadm: introduce static defaults for unit tests

Add DefaultedStaticInitConfiguration() which can be
used instead of DefaultedInitConfiguration() during unit tests.

The later can be slow since it performs dynamic defaulting.
This commit is contained in:
Lubomir I. Ivanov 2021-01-29 17:10:41 +02:00
parent 952e6f4451
commit 6578e0f6c5
10 changed files with 75 additions and 91 deletions

View File

@ -53,16 +53,6 @@ import (
utilsexec "k8s.io/utils/exec"
)
var (
// placeholderToken is only set statically to make kubeadm not randomize the token on every run
placeholderToken = kubeadmapiv1beta2.BootstrapToken{
Token: &kubeadmapiv1beta2.BootstrapTokenString{
ID: "abcdef",
Secret: "0123456789abcdef",
},
}
)
// newCmdConfig returns cobra.Command for "kubeadm config" command
func newCmdConfig(out io.Writer) *cobra.Command {
var kubeConfigFile string
@ -129,7 +119,7 @@ func newCmdConfigPrintActionDefaults(out io.Writer, action string, configBytesPr
Note that sensitive values like the Bootstrap Token fields are replaced with placeholder values like %q in order to pass validation but
not perform the real computation for creating a token.
`), action, action, placeholderToken),
`), action, action, configutil.PlaceholderToken),
RunE: func(cmd *cobra.Command, args []string) error {
groups, err := mapLegacyKindsToGroups(kinds)
if err != nil {
@ -164,7 +154,7 @@ func runConfigPrintActionDefaults(out io.Writer, componentConfigs []string, conf
}
func getDefaultComponentConfigBytes(group string) ([]byte, error) {
defaultedInitConfig, err := getDefaultedInitConfig()
defaultedInitConfig, err := configutil.DefaultedStaticInitConfiguration()
if err != nil {
return []byte{}, err
}
@ -206,22 +196,8 @@ func mapLegacyKindsToGroups(kinds []string) ([]string, error) {
return groups, nil
}
func getDefaultedInitConfig() (*kubeadmapi.InitConfiguration, error) {
initCfg := &kubeadmapiv1beta2.InitConfiguration{
LocalAPIEndpoint: kubeadmapiv1beta2.APIEndpoint{AdvertiseAddress: "1.2.3.4"},
BootstrapTokens: []kubeadmapiv1beta2.BootstrapToken{placeholderToken},
NodeRegistration: kubeadmapiv1beta2.NodeRegistrationOptions{
CRISocket: constants.DefaultDockerCRISocket, // avoid CRI detection
},
}
clusterCfg := &kubeadmapiv1beta2.ClusterConfiguration{
KubernetesVersion: constants.CurrentKubernetesVersion.String(), // avoid going to the Internet for the current Kubernetes version
}
return configutil.DefaultedInitConfiguration(initCfg, clusterCfg)
}
func getDefaultInitConfigBytes() ([]byte, error) {
internalcfg, err := getDefaultedInitConfig()
internalcfg, err := configutil.DefaultedStaticInitConfiguration()
if err != nil {
return []byte{}, err
}
@ -233,7 +209,7 @@ func getDefaultNodeConfigBytes() ([]byte, error) {
internalcfg, err := configutil.DefaultedJoinConfiguration(&kubeadmapiv1beta2.JoinConfiguration{
Discovery: kubeadmapiv1beta2.Discovery{
BootstrapToken: &kubeadmapiv1beta2.BootstrapTokenDiscovery{
Token: placeholderToken.Token.String(),
Token: configutil.PlaceholderToken.Token.String(),
APIServerEndpoint: "kube-apiserver:6443",
UnsafeSkipCAVerification: true, // TODO: UnsafeSkipCAVerification: true needs to be set for validation to pass, but shouldn't be recommended as the default
},

View File

@ -11,8 +11,7 @@ go_test(
srcs = ["proxy_test.go"],
embed = [":go_default_library"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm/v1beta2:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/util:go_default_library",
"//cmd/kubeadm/app/util/config:go_default_library",
"//staging/src/k8s.io/api/apps/v1:go_default_library",

View File

@ -27,8 +27,7 @@ import (
clientsetfake "k8s.io/client-go/kubernetes/fake"
clientsetscheme "k8s.io/client-go/kubernetes/scheme"
core "k8s.io/client-go/testing"
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
)
@ -169,21 +168,22 @@ func TestEnsureProxyAddon(t *testing.T) {
t.Run(tc.name, func(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
controlPlaneConfig := &kubeadmapiv1beta2.InitConfiguration{
LocalAPIEndpoint: kubeadmapiv1beta2.APIEndpoint{
AdvertiseAddress: "1.2.3.4",
BindPort: 1234,
},
initConfiguration, err := configutil.DefaultedStaticInitConfiguration()
if err != nil {
t.Errorf("test failed to convert external to internal version: %v", err)
return
}
controlPlaneClusterConfig := &kubeadmapiv1beta2.ClusterConfiguration{
Networking: kubeadmapiv1beta2.Networking{
PodSubnet: "5.6.7.8/24",
},
ImageRepository: "someRepo",
KubernetesVersion: constants.MinimumControlPlaneVersion.String(),
initConfiguration.LocalAPIEndpoint = kubeadmapi.APIEndpoint{
AdvertiseAddress: "1.2.3.4",
BindPort: 1234,
}
initConfiguration.ClusterConfiguration.Networking.PodSubnet = "5.6.7.8/24"
initConfiguration.ClusterConfiguration.ImageRepository = "someRepo"
// Simulate an error if necessary
switch tc.simError {
case ServiceAccountError:
@ -191,18 +191,13 @@ func TestEnsureProxyAddon(t *testing.T) {
return true, nil, apierrors.NewUnauthorized("")
})
case InvalidControlPlaneEndpoint:
controlPlaneConfig.LocalAPIEndpoint.AdvertiseAddress = "1.2.3"
initConfiguration.LocalAPIEndpoint.AdvertiseAddress = "1.2.3"
case IPv6SetBindAddress:
controlPlaneConfig.LocalAPIEndpoint.AdvertiseAddress = "1:2::3:4"
controlPlaneClusterConfig.Networking.PodSubnet = "2001:101::/48"
initConfiguration.LocalAPIEndpoint.AdvertiseAddress = "1:2::3:4"
initConfiguration.ClusterConfiguration.Networking.PodSubnet = "2001:101::/48"
}
intControlPlane, err := configutil.DefaultedInitConfiguration(controlPlaneConfig, controlPlaneClusterConfig)
if err != nil {
t.Errorf("test failed to convert external to internal version: %v", err)
return
}
err = EnsureProxyAddon(&intControlPlane.ClusterConfiguration, &intControlPlane.LocalAPIEndpoint, client)
err = EnsureProxyAddon(&initConfiguration.ClusterConfiguration, &initConfiguration.LocalAPIEndpoint, client)
// Compare actual to expected errors
actErr := "No error"

View File

@ -36,8 +36,6 @@ go_test(
embed = [":go_default_library"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta2:go_default_library",
"//cmd/kubeadm/app/constants: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",

View File

@ -25,8 +25,6 @@ import (
"k8s.io/apimachinery/pkg/util/version"
"k8s.io/client-go/kubernetes/fake"
core "k8s.io/client-go/testing"
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
)
@ -51,12 +49,9 @@ func TestCreateConfigMap(t *testing.T) {
return true, nil, nil
})
clusterCfg := &kubeadmapiv1beta2.ClusterConfiguration{
KubernetesVersion: constants.CurrentKubernetesVersion.String(),
}
internalcfg, err := configutil.DefaultedInitConfiguration(&kubeadmapiv1beta2.InitConfiguration{}, clusterCfg)
internalcfg, err := configutil.DefaultedStaticInitConfiguration()
if err != nil {
t.Fatalf("unexpected failure by DefaultedInitConfiguration: %v", err)
t.Fatalf("unexpected failure when defaulting InitConfiguration: %v", err)
}
if err := CreateConfigMap(&internalcfg.ClusterConfiguration, client); err != nil {

View File

@ -44,7 +44,6 @@ go_test(
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta2:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/util/config:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",

View File

@ -27,7 +27,6 @@ import (
clientsetfake "k8s.io/client-go/kubernetes/fake"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
)
@ -50,33 +49,14 @@ func TestUploadConfiguration(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t2 *testing.T) {
initialcfg := &kubeadmapiv1beta2.InitConfiguration{
LocalAPIEndpoint: kubeadmapiv1beta2.APIEndpoint{
AdvertiseAddress: "1.2.3.4",
},
BootstrapTokens: []kubeadmapiv1beta2.BootstrapToken{
{
Token: &kubeadmapiv1beta2.BootstrapTokenString{
ID: "abcdef",
Secret: "abcdef0123456789",
},
},
},
NodeRegistration: kubeadmapiv1beta2.NodeRegistrationOptions{
Name: "node-foo",
CRISocket: "/var/run/custom-cri.sock",
},
}
clustercfg := &kubeadmapiv1beta2.ClusterConfiguration{
KubernetesVersion: kubeadmconstants.MinimumControlPlaneVersion.WithPatch(10).String(),
}
cfg, err := configutil.DefaultedInitConfiguration(initialcfg, clustercfg)
cfg, err := configutil.DefaultedStaticInitConfiguration()
if err != nil {
t2.Fatalf("UploadConfiguration() error = %v", err)
}
cfg.ComponentConfigs = kubeadmapi.ComponentConfigMap{}
cfg.ClusterConfiguration.KubernetesVersion = kubeadmconstants.MinimumControlPlaneVersion.WithPatch(10).String()
cfg.NodeRegistration.Name = "node-foo"
cfg.NodeRegistration.CRISocket = kubeadmconstants.UnknownCRISocket
status := &kubeadmapi.ClusterStatus{
APIEndpoints: map[string]kubeadmapi.APIEndpoint{
@ -117,7 +97,7 @@ func TestUploadConfiguration(t *testing.T) {
decodedCfg.ComponentConfigs = kubeadmapi.ComponentConfigMap{}
if !reflect.DeepEqual(decodedCfg, &cfg.ClusterConfiguration) {
t2.Errorf("the initial and decoded ClusterConfiguration didn't match:\n%t\n===\n%t", decodedCfg.ComponentConfigs == nil, cfg.ComponentConfigs == nil)
t2.Errorf("the initial and decoded ClusterConfiguration didn't match:\n%#v\n===\n%#v", decodedCfg, &cfg.ClusterConfiguration)
}
statusData := controlPlaneCfg.Data[kubeadmconstants.ClusterStatusConfigMapKey]

View File

@ -36,12 +36,23 @@ import (
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
"k8s.io/kubernetes/cmd/kubeadm/app/util/config/strict"
kubeadmruntime "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime"
)
var (
// PlaceholderToken is only set statically to make kubeadm not randomize the token on every run
PlaceholderToken = kubeadmapiv1beta2.BootstrapToken{
Token: &kubeadmapiv1beta2.BootstrapTokenString{
ID: "abcdef",
Secret: "0123456789abcdef",
},
}
)
// SetInitDynamicDefaults checks and sets configuration values for the InitConfiguration object
func SetInitDynamicDefaults(cfg *kubeadmapi.InitConfiguration) error {
if err := SetBootstrapTokensDynamicDefaults(&cfg.BootstrapTokens); err != nil {
@ -169,6 +180,40 @@ func SetClusterDynamicDefaults(cfg *kubeadmapi.ClusterConfiguration, localAPIEnd
return nil
}
// DefaultedStaticInitConfiguration returns the internal InitConfiguration with static defaults.
func DefaultedStaticInitConfiguration() (*kubeadmapi.InitConfiguration, error) {
versionedInitCfg := &kubeadmapiv1beta2.InitConfiguration{
LocalAPIEndpoint: kubeadmapiv1beta2.APIEndpoint{AdvertiseAddress: "1.2.3.4"},
BootstrapTokens: []kubeadmapiv1beta2.BootstrapToken{PlaceholderToken},
NodeRegistration: kubeadmapiv1beta2.NodeRegistrationOptions{
CRISocket: constants.DefaultDockerCRISocket, // avoid CRI detection
Name: "node",
},
}
versionedClusterCfg := &kubeadmapiv1beta2.ClusterConfiguration{
KubernetesVersion: constants.CurrentKubernetesVersion.String(), // avoid going to the Internet for the current Kubernetes version
}
internalcfg := &kubeadmapi.InitConfiguration{}
// 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(versionedInitCfg)
if err := kubeadmscheme.Scheme.Convert(versionedInitCfg, internalcfg, nil); err != nil {
return nil, err
}
kubeadmscheme.Scheme.Default(versionedClusterCfg)
if err := kubeadmscheme.Scheme.Convert(versionedClusterCfg, &internalcfg.ClusterConfiguration, nil); err != nil {
return nil, err
}
// Default all the embedded ComponentConfig structs
componentconfigs.Default(&internalcfg.ClusterConfiguration, &internalcfg.LocalAPIEndpoint, &internalcfg.NodeRegistration)
return internalcfg, nil
}
// DefaultedInitConfiguration takes a versioned init config (often populated by flags), defaults it and converts it into internal InitConfiguration
func DefaultedInitConfiguration(versionedInitCfg *kubeadmapiv1beta2.InitConfiguration, versionedClusterCfg *kubeadmapiv1beta2.ClusterConfiguration) (*kubeadmapi.InitConfiguration, error) {
internalcfg := &kubeadmapi.InitConfiguration{}

View File

@ -11,7 +11,6 @@ go_library(
importpath = "k8s.io/kubernetes/cmd/kubeadm/test",
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta2:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/util/certs:go_default_library",
"//cmd/kubeadm/app/util/config:go_default_library",

View File

@ -23,7 +23,6 @@ import (
"testing"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
certtestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
@ -114,10 +113,9 @@ 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.DefaultedInitConfiguration(&kubeadmapiv1beta2.InitConfiguration{}, &kubeadmapiv1beta2.ClusterConfiguration{})
internalcfg, err := configutil.DefaultedStaticInitConfiguration()
if err != nil {
t.Fatalf("unexpected error getting default config: %v", err)
}
return internalcfg
}