Skip to content

Commit 8009530

Browse files
committed
kubeadm: FeatureGate MergeCLIArgumentsWithConfig is added for ignorePreflightErrors
Turn on FeatureGate MergeCLIArgumentsWithConfig to keep the legacy way of management of ignorePreflightErrors, which means the value defined by the flag `ignore-preflight-errors` will be merged with the value `ignorePreflightErrors` defined in the config file. Otherwise, the value defined by the flag will replace the value from the config file if set. Signed-off-by: Dave Chen <[email protected]>
1 parent 8e2b12a commit 8009530

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
@@ -638,15 +638,21 @@ func ValidateCertificateKey(certificateKey string, fldPath *field.Path) field.Er
638638
// ValidateIgnorePreflightErrors validates duplicates in:
639639
// - ignore-preflight-errors flag and
640640
// - ignorePreflightErrors field in {Init,Join}Configuration files.
641-
func ValidateIgnorePreflightErrors(ignorePreflightErrorsFromCLI, ignorePreflightErrorsFromConfigFile []string) (sets.Set[string], error) {
641+
// and make sure ignore "all" cannot configured with individual checks.
642+
func ValidateIgnorePreflightErrors(featureList map[string]bool, ignorePreflightErrorsFromCLI, ignorePreflightErrorsFromConfigFile []string) (sets.Set[string], error) {
642643
ignoreErrors := sets.New[string]()
643644
allErrs := field.ErrorList{}
645+
ignorePreflightErr := ignorePreflightErrorsFromConfigFile
644646

645-
for _, item := range ignorePreflightErrorsFromConfigFile {
646-
ignoreErrors.Insert(strings.ToLower(item)) // parameters are case insensitive
647+
if ignorePreflightErrorsFromCLI != nil {
648+
if features.Enabled(featureList, features.MergeCLIArgumentsWithConfig) {
649+
ignorePreflightErr = append(ignorePreflightErr, ignorePreflightErrorsFromCLI...)
650+
} else {
651+
ignorePreflightErr = ignorePreflightErrorsFromCLI
652+
}
647653
}
648654

649-
for _, item := range ignorePreflightErrorsFromCLI {
655+
for _, item := range ignorePreflightErr {
650656
ignoreErrors.Insert(strings.ToLower(item)) // parameters are case insensitive
651657
}
652658

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) {
@@ -799,82 +800,118 @@ func TestValidateIgnorePreflightErrors(t *testing.T) {
799800
ignorePreflightErrorsFromConfigFile []string
800801
expectedSet sets.Set[string]
801802
expectedError bool
803+
mergeCLIArgumentsWithConfig bool
802804
}{
805+
// FG is off
803806
{ // empty lists in CLI and config file
804807
[]string{},
805808
[]string{},
806809
sets.New[string](),
807810
false,
808-
},
809-
{ // empty list in CLI only
810-
[]string{},
811-
[]string{"a"},
812-
sets.New("a"),
813811
false,
814812
},
815813
{ // empty list in config file only
816814
[]string{"a"},
817815
[]string{},
818816
sets.New("a"),
819817
false,
818+
false,
820819
},
821820
{ // no duplicates, no overlap
822821
[]string{"a", "b"},
823822
[]string{"c", "d"},
824-
sets.New("a", "b", "c", "d"),
823+
sets.New("a", "b"),
824+
false,
825825
false,
826826
},
827827
{ // some duplicates, with some overlapping duplicates
828828
[]string{"a", "b", "a"},
829829
[]string{"c", "b"},
830-
sets.New("a", "b", "c"),
830+
sets.New("a", "b"),
831+
false,
831832
false,
832833
},
833-
{ // empty list in CLI, but 'all' present in config file
834-
[]string{},
834+
{ // CLI is not set, but 'all' present in config file
835+
nil,
835836
[]string{"all"},
836837
sets.New("all"),
837838
false,
839+
false,
838840
},
839841
{ // empty list in config file, but 'all' present in CLI
840842
[]string{"all"},
841843
[]string{},
842844
sets.New("all"),
843845
false,
846+
false,
844847
},
845848
{ // some duplicates, only 'all' present in CLI and config file
846849
[]string{"all"},
847850
[]string{"all"},
848851
sets.New("all"),
849852
false,
853+
false,
850854
},
851855
{ // non-duplicate, but 'all' present together with individual checks in CLI
852856
[]string{"a", "b", "all"},
853857
[]string{},
854858
sets.New[string](),
855859
true,
860+
false,
856861
},
857862
{ // non-duplicate, but 'all' present together with individual checks in config file
858-
[]string{},
863+
nil,
859864
[]string{"a", "b", "all"},
860865
sets.New[string](),
861866
true,
867+
false,
862868
},
863-
{ // non-duplicate, but 'all' present in config file, while values are in CLI, which is forbidden
869+
{ // non-duplicate, but 'all' present in config file, while values are in CLI, "all" from config file will be ignored
864870
[]string{"a", "b"},
865871
[]string{"all"},
866-
sets.New[string](),
867-
true,
872+
sets.New[string]("a", "b"),
873+
false,
874+
false,
868875
},
869-
{ // non-duplicate, but 'all' present in CLI, while values are in config file, which is forbidden
876+
{ // non-duplicate, but 'all' present in CLI, while values are in config file, values from config file will be ignored
870877
[]string{"all"},
871878
[]string{"a", "b"},
879+
sets.New[string]("all"),
880+
false,
881+
false,
882+
},
883+
{ // set from CLI will take precedence of the config file
884+
[]string{"a", "b"},
885+
[]string{"c", "d"},
886+
sets.New[string]("a", "b"),
887+
false,
888+
false,
889+
},
890+
{ // empty list in CLI only
891+
[]string{},
892+
[]string{"a"},
872893
sets.New[string](),
894+
false,
895+
false,
896+
},
897+
{ // flag from CLI is not set
898+
nil,
899+
[]string{"c", "d"},
900+
sets.New[string]("c", "d"),
901+
false,
902+
false,
903+
},
904+
// FG is on
905+
{
906+
[]string{"a", "b"},
907+
[]string{"c", "d"},
908+
sets.New[string]("a", "b", "c", "d"),
909+
false,
873910
true,
874911
},
875912
}
876913
for _, rt := range tests {
877-
result, err := ValidateIgnorePreflightErrors(rt.ignorePreflightErrorsFromCLI, rt.ignorePreflightErrorsFromConfigFile)
914+
result, err := ValidateIgnorePreflightErrors(map[string]bool{features.MergeCLIArgumentsWithConfig: rt.mergeCLIArgumentsWithConfig}, rt.ignorePreflightErrorsFromCLI, rt.ignorePreflightErrorsFromConfigFile)
878915
switch {
879916
case err != nil && !rt.expectedError:
880917
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
@@ -306,7 +306,7 @@ func newInitData(cmd *cobra.Command, args []string, initOptions *initOptions, ou
306306
return nil, err
307307
}
308308

309-
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(initOptions.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
309+
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(cfg.FeatureGates, initOptions.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
310310
if err != nil {
311311
return nil, err
312312
}

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
@@ -225,7 +225,7 @@ func newCmdJoin(out io.Writer, joinOptions *joinOptions) *cobra.Command {
225225
// assume that the command execution does not depend on CRISocket when --cri-socket flag is not set
226226
joinOptions.externalcfg.NodeRegistration.CRISocket = kubeadmconstants.UnknownCRISocket
227227
}
228-
data, err := newJoinData(cmd, args, joinOptions, out, kubeadmconstants.GetAdminKubeConfigPath())
228+
data, err := newJoinData(cmd, args, joinOptions, out, kubeadmconstants.GetAdminKubeConfigPath(), false)
229229
if err != nil {
230230
return nil, err
231231
}
@@ -334,8 +334,10 @@ func newJoinOptions() *joinOptions {
334334

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

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

434-
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(opt.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
436+
initCfg := &kubeadmapi.InitConfiguration{}
437+
if !lazilyFetchInitCfg {
438+
if tlsBootstrapCfg == nil {
439+
if tlsBootstrapCfg, err = discovery.For(cfg); err != nil {
440+
return nil, err
441+
}
442+
}
443+
if initCfg, err = fetchInitConfigurationFromJoinConfiguration(cfg, tlsBootstrapCfg); err != nil {
444+
return nil, err
445+
}
446+
}
447+
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(initCfg.FeatureGates, opt.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors)
435448
if err != nil {
436449
return nil, err
437450
}
@@ -463,6 +476,7 @@ func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Wri
463476
return &joinData{
464477
cfg: cfg,
465478
dryRun: cmdutil.ValueFromFlagsOrConfig(cmd.Flags(), options.DryRun, cfg.DryRun, opt.dryRun).(bool),
479+
initCfg: initCfg,
466480
tlsBootstrapCfg: tlsBootstrapCfg,
467481
ignorePreflightErrors: ignorePreflightErrorsSet,
468482
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
@@ -104,7 +104,7 @@ func newResetData(cmd *cobra.Command, opts *resetOptions, in io.Reader, out io.W
104104
return nil, err
105105
}
106106

107-
var initCfg *kubeadmapi.InitConfiguration
107+
initCfg := &kubeadmapi.InitConfiguration{}
108108

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

126-
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(opts.ignorePreflightErrors, resetCfg.IgnorePreflightErrors)
126+
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(initCfg.FeatureGates, opts.ignorePreflightErrors, resetCfg.IgnorePreflightErrors)
127127
if err != nil {
128128
return nil, err
129129
}

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)