Skip to content

Commit 3548ef0

Browse files
authored
Merge pull request kubernetes#119946 from chendave/ignore_preflight_error
kubeadm: FeatureGate MergeCLIArgumentsWithConfig is added for ignorePreflightErrors
2 parents 4254a77 + 8009530 commit 3548ef0

File tree

11 files changed

+95
-32
lines changed

11 files changed

+95
-32
lines changed

cmd/kubeadm/app/apis/kubeadm/validation/validation.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -650,15 +650,21 @@ func ValidateCertificateKey(certificateKey string, fldPath *field.Path) field.Er
650650
// ValidateIgnorePreflightErrors validates duplicates in:
651651
// - ignore-preflight-errors flag and
652652
// - ignorePreflightErrors field in {Init,Join}Configuration files.
653-
func ValidateIgnorePreflightErrors(ignorePreflightErrorsFromCLI, ignorePreflightErrorsFromConfigFile []string) (sets.Set[string], error) {
653+
// and make sure ignore "all" cannot configured with individual checks.
654+
func ValidateIgnorePreflightErrors(featureList map[string]bool, ignorePreflightErrorsFromCLI, ignorePreflightErrorsFromConfigFile []string) (sets.Set[string], error) {
654655
ignoreErrors := sets.New[string]()
655656
allErrs := field.ErrorList{}
657+
ignorePreflightErr := ignorePreflightErrorsFromConfigFile
656658

657-
for _, item := range ignorePreflightErrorsFromConfigFile {
658-
ignoreErrors.Insert(strings.ToLower(item)) // parameters are case insensitive
659+
if ignorePreflightErrorsFromCLI != nil {
660+
if features.Enabled(featureList, features.MergeCLIArgumentsWithConfig) {
661+
ignorePreflightErr = append(ignorePreflightErr, ignorePreflightErrorsFromCLI...)
662+
} else {
663+
ignorePreflightErr = ignorePreflightErrorsFromCLI
664+
}
659665
}
660666

661-
for _, item := range ignorePreflightErrorsFromCLI {
667+
for _, item := range ignorePreflightErr {
662668
ignoreErrors.Insert(strings.ToLower(item)) // parameters are case insensitive
663669
}
664670

cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929

3030
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
3131
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
32+
"k8s.io/kubernetes/cmd/kubeadm/app/features"
3233
)
3334

3435
func TestValidateToken(t *testing.T) {
@@ -805,82 +806,118 @@ func TestValidateIgnorePreflightErrors(t *testing.T) {
805806
ignorePreflightErrorsFromConfigFile []string
806807
expectedSet sets.Set[string]
807808
expectedError bool
809+
mergeCLIArgumentsWithConfig bool
808810
}{
811+
// FG is off
809812
{ // empty lists in CLI and config file
810813
[]string{},
811814
[]string{},
812815
sets.New[string](),
813816
false,
814-
},
815-
{ // empty list in CLI only
816-
[]string{},
817-
[]string{"a"},
818-
sets.New("a"),
819817
false,
820818
},
821819
{ // empty list in config file only
822820
[]string{"a"},
823821
[]string{},
824822
sets.New("a"),
825823
false,
824+
false,
826825
},
827826
{ // no duplicates, no overlap
828827
[]string{"a", "b"},
829828
[]string{"c", "d"},
830-
sets.New("a", "b", "c", "d"),
829+
sets.New("a", "b"),
830+
false,
831831
false,
832832
},
833833
{ // some duplicates, with some overlapping duplicates
834834
[]string{"a", "b", "a"},
835835
[]string{"c", "b"},
836-
sets.New("a", "b", "c"),
836+
sets.New("a", "b"),
837+
false,
837838
false,
838839
},
839-
{ // empty list in CLI, but 'all' present in config file
840-
[]string{},
840+
{ // CLI is not set, but 'all' present in config file
841+
nil,
841842
[]string{"all"},
842843
sets.New("all"),
843844
false,
845+
false,
844846
},
845847
{ // empty list in config file, but 'all' present in CLI
846848
[]string{"all"},
847849
[]string{},
848850
sets.New("all"),
849851
false,
852+
false,
850853
},
851854
{ // some duplicates, only 'all' present in CLI and config file
852855
[]string{"all"},
853856
[]string{"all"},
854857
sets.New("all"),
855858
false,
859+
false,
856860
},
857861
{ // non-duplicate, but 'all' present together with individual checks in CLI
858862
[]string{"a", "b", "all"},
859863
[]string{},
860864
sets.New[string](),
861865
true,
866+
false,
862867
},
863868
{ // non-duplicate, but 'all' present together with individual checks in config file
864-
[]string{},
869+
nil,
865870
[]string{"a", "b", "all"},
866871
sets.New[string](),
867872
true,
873+
false,
868874
},
869-
{ // non-duplicate, but 'all' present in config file, while values are in CLI, which is forbidden
875+
{ // non-duplicate, but 'all' present in config file, while values are in CLI, "all" from config file will be ignored
870876
[]string{"a", "b"},
871877
[]string{"all"},
872-
sets.New[string](),
873-
true,
878+
sets.New[string]("a", "b"),
879+
false,
880+
false,
874881
},
875-
{ // non-duplicate, but 'all' present in CLI, while values are in config file, which is forbidden
882+
{ // non-duplicate, but 'all' present in CLI, while values are in config file, values from config file will be ignored
876883
[]string{"all"},
877884
[]string{"a", "b"},
885+
sets.New[string]("all"),
886+
false,
887+
false,
888+
},
889+
{ // set from CLI will take precedence of the config file
890+
[]string{"a", "b"},
891+
[]string{"c", "d"},
892+
sets.New[string]("a", "b"),
893+
false,
894+
false,
895+
},
896+
{ // empty list in CLI only
897+
[]string{},
898+
[]string{"a"},
878899
sets.New[string](),
900+
false,
901+
false,
902+
},
903+
{ // flag from CLI is not set
904+
nil,
905+
[]string{"c", "d"},
906+
sets.New[string]("c", "d"),
907+
false,
908+
false,
909+
},
910+
// FG is on
911+
{
912+
[]string{"a", "b"},
913+
[]string{"c", "d"},
914+
sets.New[string]("a", "b", "c", "d"),
915+
false,
879916
true,
880917
},
881918
}
882919
for _, rt := range tests {
883-
result, err := ValidateIgnorePreflightErrors(rt.ignorePreflightErrorsFromCLI, rt.ignorePreflightErrorsFromConfigFile)
920+
result, err := ValidateIgnorePreflightErrors(map[string]bool{features.MergeCLIArgumentsWithConfig: rt.mergeCLIArgumentsWithConfig}, rt.ignorePreflightErrorsFromCLI, rt.ignorePreflightErrorsFromConfigFile)
884921
switch {
885922
case err != nil && !rt.expectedError:
886923
t.Errorf("ValidateIgnorePreflightErrors: unexpected error for input (%s, %s), error: %v", rt.ignorePreflightErrorsFromCLI, rt.ignorePreflightErrorsFromConfigFile, err)

cmd/kubeadm/app/cmd/init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ func newInitData(cmd *cobra.Command, args []string, initOptions *initOptions, ou
309309
return nil, err
310310
}
311311

312-
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(initOptions.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
312+
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(cfg.FeatureGates, initOptions.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
313313
if err != nil {
314314
return nil, err
315315
}

cmd/kubeadm/app/cmd/init_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ func TestNewInitData(t *testing.T) {
181181
options.CfgPath: configFilePath,
182182
options.IgnorePreflightErrors: "a,b",
183183
},
184-
validate: expectedInitIgnorePreflightErrors("a", "b", "c", "d"),
184+
validate: expectedInitIgnorePreflightErrors("a", "b"),
185185
},
186186
}
187187
for _, tc := range testCases {

cmd/kubeadm/app/cmd/join.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ func newCmdJoin(out io.Writer, joinOptions *joinOptions) *cobra.Command {
226226
// assume that the command execution does not depend on CRISocket when --cri-socket flag is not set
227227
joinOptions.skipCRIDetect = true
228228
}
229-
data, err := newJoinData(cmd, args, joinOptions, out, kubeadmconstants.GetAdminKubeConfigPath())
229+
data, err := newJoinData(cmd, args, joinOptions, out, kubeadmconstants.GetAdminKubeConfigPath(), false)
230230
if err != nil {
231231
return nil, err
232232
}
@@ -335,8 +335,10 @@ func newJoinOptions() *joinOptions {
335335

336336
// newJoinData returns a new joinData struct to be used for the execution of the kubeadm join workflow.
337337
// This func takes care of validating joinOptions passed to the command, and then it converts
338-
// options into the internal JoinConfiguration type that is used as input all the phases in the kubeadm join workflow
339-
func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Writer, adminKubeConfigPath string) (*joinData, error) {
338+
// options into the internal JoinConfiguration type that is used as input all the phases in the kubeadm join workflow.
339+
// Set the lazilyFetchInitCfg to true to lazily fetch the InitConfiguration from cluster, e.g. unittest to test joinData
340+
// without the interaction with cluster.
341+
func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Writer, adminKubeConfigPath string, lazilyFetchInitCfg bool) (*joinData, error) {
340342

341343
// Validate the mixed arguments with --config and return early on errors
342344
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
@@ -434,7 +436,18 @@ func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Wri
434436
return nil, err
435437
}
436438

437-
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(opt.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
439+
initCfg := &kubeadmapi.InitConfiguration{}
440+
if !lazilyFetchInitCfg {
441+
if tlsBootstrapCfg == nil {
442+
if tlsBootstrapCfg, err = discovery.For(cfg); err != nil {
443+
return nil, err
444+
}
445+
}
446+
if initCfg, err = fetchInitConfigurationFromJoinConfiguration(cfg, tlsBootstrapCfg); err != nil {
447+
return nil, err
448+
}
449+
}
450+
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(initCfg.FeatureGates, opt.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
438451
if err != nil {
439452
return nil, err
440453
}
@@ -466,6 +479,7 @@ func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Wri
466479
return &joinData{
467480
cfg: cfg,
468481
dryRun: cmdutil.ValueFromFlagsOrConfig(cmd.Flags(), options.DryRun, cfg.DryRun, opt.dryRun).(bool),
482+
initCfg: initCfg,
469483
tlsBootstrapCfg: tlsBootstrapCfg,
470484
ignorePreflightErrors: ignorePreflightErrorsSet,
471485
outputWriter: out,

cmd/kubeadm/app/cmd/join_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ func TestNewJoinData(t *testing.T) {
289289
options.CfgPath: configFilePath,
290290
options.IgnorePreflightErrors: "a,b",
291291
},
292-
validate: expectedJoinIgnorePreflightErrors(sets.New("a", "b", "c", "d")),
292+
validate: expectedJoinIgnorePreflightErrors(sets.New("a", "b")),
293293
},
294294
{
295295
name: "warn if --control-plane flag is not set",
@@ -335,7 +335,7 @@ func TestNewJoinData(t *testing.T) {
335335
}
336336

337337
// test newJoinData method
338-
data, err := newJoinData(cmd, tc.args, joinOptions, nil, kubeconfigFilePath)
338+
data, err := newJoinData(cmd, tc.args, joinOptions, nil, kubeconfigFilePath, true)
339339
klog.Flush()
340340
msg := "WARNING: --control-plane is also required when passing control-plane"
341341
if tc.expectWarn {

cmd/kubeadm/app/cmd/reset.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func newResetData(cmd *cobra.Command, opts *resetOptions, in io.Reader, out io.W
105105
return nil, err
106106
}
107107

108-
var initCfg *kubeadmapi.InitConfiguration
108+
initCfg := &kubeadmapi.InitConfiguration{}
109109

110110
// Either use the config file if specified, or convert public kubeadm API to the internal ResetConfiguration and validates cfg.
111111
resetCfg, err := configutil.LoadOrDefaultResetConfiguration(opts.cfgPath, opts.externalcfg, configutil.LoadOrDefaultConfigurationOptions{
@@ -127,7 +127,7 @@ func newResetData(cmd *cobra.Command, opts *resetOptions, in io.Reader, out io.W
127127
klog.V(1).Infof("[reset] Could not obtain a client set from the kubeconfig file: %s", opts.kubeconfigPath)
128128
}
129129

130-
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(opts.ignorePreflightErrors, resetCfg.IgnorePreflightErrors)
130+
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(initCfg.FeatureGates, opts.ignorePreflightErrors, resetCfg.IgnorePreflightErrors)
131131
if err != nil {
132132
return nil, err
133133
}

cmd/kubeadm/app/cmd/reset_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func TestNewResetData(t *testing.T) {
209209
options.CfgPath: configFilePath,
210210
options.IgnorePreflightErrors: "c,d",
211211
},
212-
validate: expectedResetIgnorePreflightErrors(sets.New("a", "b", "c", "d")),
212+
validate: expectedResetIgnorePreflightErrors(sets.New("c", "d")),
213213
},
214214
}
215215
for _, tc := range testCases {

cmd/kubeadm/app/cmd/upgrade/common.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ func enforceRequirements(flags *applyPlanFlags, args []string, dryRun bool, upgr
175175
}
176176
}
177177

178-
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(flags.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
178+
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(cfg.FeatureGates, flags.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
179179
if err != nil {
180180
return nil, nil, nil, err
181181
}

cmd/kubeadm/app/cmd/upgrade/node.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ func newNodeData(cmd *cobra.Command, args []string, options *nodeOptions, out io
153153
return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap")
154154
}
155155

156-
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(options.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
156+
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(cfg.FeatureGates, options.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
157157
if err != nil {
158158
return nil, err
159159
}

0 commit comments

Comments
 (0)