Skip to content

Commit e1b79ab

Browse files
authored
Merge pull request kubernetes#74831 from fabriziopandini/remove-discovery-flags
Remove discovery flags from kubeadm join phases (when possible)
2 parents 6b28827 + 5ecd74a commit e1b79ab

File tree

4 files changed

+82
-56
lines changed

4 files changed

+82
-56
lines changed

cmd/kubeadm/app/cmd/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ go_library(
5858
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
5959
"//staging/src/k8s.io/apimachinery/pkg/version:go_default_library",
6060
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
61+
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
6162
"//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library",
6263
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
6364
"//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library",

cmd/kubeadm/app/cmd/join.go

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
flag "github.com/spf13/pflag"
2929
"k8s.io/apimachinery/pkg/util/sets"
3030
clientset "k8s.io/client-go/kubernetes"
31+
clientcmd "k8s.io/client-go/tools/clientcmd"
3132
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
3233
"k8s.io/klog"
3334
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
@@ -308,44 +309,57 @@ func newJoinOptions() *joinOptions {
308309
// newJoinData returns a new joinData struct to be used for the execution of the kubeadm join workflow.
309310
// This func takes care of validating joinOptions passed to the command, and then it converts
310311
// options into the internal JoinConfiguration type that is used as input all the phases in the kubeadm join workflow
311-
func newJoinData(cmd *cobra.Command, args []string, options *joinOptions, out io.Writer) (*joinData, error) {
312+
func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Writer) (*joinData, error) {
312313
// Re-apply defaults to the public kubeadm API (this will set only values not exposed/not set as a flags)
313-
kubeadmscheme.Scheme.Default(options.externalcfg)
314+
kubeadmscheme.Scheme.Default(opt.externalcfg)
314315

315316
// Validate standalone flags values and/or combination of flags and then assigns
316317
// validated values to the public kubeadm config API when applicable
317318

318319
// if a token is provided, use this value for both discovery-token and tls-bootstrap-token when those values are not provided
319-
if len(options.token) > 0 {
320-
if len(options.externalcfg.Discovery.TLSBootstrapToken) == 0 {
321-
options.externalcfg.Discovery.TLSBootstrapToken = options.token
320+
if len(opt.token) > 0 {
321+
if len(opt.externalcfg.Discovery.TLSBootstrapToken) == 0 {
322+
opt.externalcfg.Discovery.TLSBootstrapToken = opt.token
322323
}
323-
if len(options.externalcfg.Discovery.BootstrapToken.Token) == 0 {
324-
options.externalcfg.Discovery.BootstrapToken.Token = options.token
324+
if len(opt.externalcfg.Discovery.BootstrapToken.Token) == 0 {
325+
opt.externalcfg.Discovery.BootstrapToken.Token = opt.token
325326
}
326327
}
327328

328329
// if a file or URL from which to load cluster information was not provided, unset the Discovery.File object
329-
if len(options.externalcfg.Discovery.File.KubeConfigPath) == 0 {
330-
options.externalcfg.Discovery.File = nil
330+
if len(opt.externalcfg.Discovery.File.KubeConfigPath) == 0 {
331+
opt.externalcfg.Discovery.File = nil
331332
}
332333

333334
// if an APIServerEndpoint from which to retrive cluster information was not provided, unset the Discovery.BootstrapToken object
334335
if len(args) == 0 {
335-
options.externalcfg.Discovery.BootstrapToken = nil
336+
opt.externalcfg.Discovery.BootstrapToken = nil
336337
} else {
337-
if len(options.cfgPath) == 0 && len(args) > 1 {
338+
if len(opt.cfgPath) == 0 && len(args) > 1 {
338339
klog.Warningf("[join] WARNING: More than one API server endpoint supplied on command line %v. Using the first one.", args)
339340
}
340-
options.externalcfg.Discovery.BootstrapToken.APIServerEndpoint = args[0]
341+
opt.externalcfg.Discovery.BootstrapToken.APIServerEndpoint = args[0]
341342
}
342343

343344
// if not joining a control plane, unset the ControlPlane object
344-
if !options.controlPlane {
345-
options.externalcfg.ControlPlane = nil
345+
if !opt.controlPlane {
346+
opt.externalcfg.ControlPlane = nil
346347
}
347348

348-
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(options.ignorePreflightErrors)
349+
// if the admin.conf file already exists, use it for skipping the discovery process.
350+
// NB. this case can happen when we are joining a control-plane node only (and phases are invoked atomically)
351+
var adminKubeConfigPath = kubeadmconstants.GetAdminKubeConfigPath()
352+
var tlsBootstrapCfg *clientcmdapi.Config
353+
if _, err := os.Stat(adminKubeConfigPath); err == nil && opt.controlPlane {
354+
// use the admin.conf as tlsBootstrapCfg, that is the kubeconfig file used for reading the kubeadm-config during discovery
355+
klog.V(1).Infof("[join] found %s. Use it for skipping discovery", adminKubeConfigPath)
356+
tlsBootstrapCfg, err = clientcmd.LoadFromFile(adminKubeConfigPath)
357+
if err != nil {
358+
return nil, errors.Wrapf(err, "Error loading %s", adminKubeConfigPath)
359+
}
360+
}
361+
362+
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(opt.ignorePreflightErrors)
349363
if err != nil {
350364
return nil, err
351365
}
@@ -356,25 +370,35 @@ func newJoinData(cmd *cobra.Command, args []string, options *joinOptions, out io
356370

357371
// Either use the config file if specified, or convert public kubeadm API to the internal JoinConfiguration
358372
// and validates JoinConfiguration
359-
if options.externalcfg.NodeRegistration.Name == "" {
373+
if opt.externalcfg.NodeRegistration.Name == "" {
360374
klog.V(1).Infoln("[join] found NodeName empty; using OS hostname as NodeName")
361375
}
362376

363-
if options.externalcfg.ControlPlane != nil && options.externalcfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress == "" {
377+
if opt.externalcfg.ControlPlane != nil && opt.externalcfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress == "" {
364378
klog.V(1).Infoln("[join] found advertiseAddress empty; using default interface's IP address as advertiseAddress")
365379
}
366380

367-
cfg, err := configutil.LoadOrDefaultJoinConfiguration(options.cfgPath, options.externalcfg)
381+
// in case the command doesn't have flags for discovery, makes the join cfg validation pass checks on discovery
382+
if cmd.Flags().Lookup(options.FileDiscovery) == nil {
383+
if _, err := os.Stat(adminKubeConfigPath); os.IsNotExist(err) {
384+
return nil, errors.Errorf("File %s does not exists. Please use 'kubeadm join phase control-plane-prepare' subcommands to generate it.", adminKubeConfigPath)
385+
}
386+
klog.V(1).Infof("[join] found discovery flags missing for this command. using FileDiscovery: %s", adminKubeConfigPath)
387+
opt.externalcfg.Discovery.File = &kubeadmapiv1beta1.FileDiscovery{KubeConfigPath: adminKubeConfigPath}
388+
opt.externalcfg.Discovery.BootstrapToken = nil //NB. this could be removed when we get better control on args (e.g. phases without discovery should have NoArgs )
389+
}
390+
391+
cfg, err := configutil.LoadOrDefaultJoinConfiguration(opt.cfgPath, opt.externalcfg)
368392
if err != nil {
369393
return nil, err
370394
}
371395

372-
// override node name and CRI socket from the command line options
373-
if options.externalcfg.NodeRegistration.Name != "" {
374-
cfg.NodeRegistration.Name = options.externalcfg.NodeRegistration.Name
396+
// override node name and CRI socket from the command line opt
397+
if opt.externalcfg.NodeRegistration.Name != "" {
398+
cfg.NodeRegistration.Name = opt.externalcfg.NodeRegistration.Name
375399
}
376-
if options.externalcfg.NodeRegistration.CRISocket != "" {
377-
cfg.NodeRegistration.CRISocket = options.externalcfg.NodeRegistration.CRISocket
400+
if opt.externalcfg.NodeRegistration.CRISocket != "" {
401+
cfg.NodeRegistration.CRISocket = opt.externalcfg.NodeRegistration.CRISocket
378402
}
379403

380404
if cfg.ControlPlane != nil {
@@ -385,9 +409,10 @@ func newJoinData(cmd *cobra.Command, args []string, options *joinOptions, out io
385409

386410
return &joinData{
387411
cfg: cfg,
412+
tlsBootstrapCfg: tlsBootstrapCfg,
388413
ignorePreflightErrors: ignorePreflightErrorsSet,
389414
outputWriter: out,
390-
certificateKey: options.certificateKey,
415+
certificateKey: opt.certificateKey,
391416
}, nil
392417
}
393418

cmd/kubeadm/app/cmd/phases/join/controlplanejoin.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,6 @@ func getControlPlaneJoinPhaseFlags() []string {
4444
options.CfgPath,
4545
options.ControlPlane,
4646
options.NodeName,
47-
options.FileDiscovery,
48-
options.TokenDiscovery,
49-
options.TokenDiscoveryCAHash,
50-
options.TokenDiscoverySkipCAHash,
51-
options.TLSBootstrapToken,
52-
options.TokenStr,
5347
}
5448
}
5549

cmd/kubeadm/app/cmd/phases/join/controlplaneprepare.go

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,9 @@ func NewControlPlanePreparePhase() workflow.Phase {
4141
Short: "Prepares the machine for serving a control plane.",
4242
Phases: []workflow.Phase{
4343
{
44-
Name: "all",
45-
Short: "Prepares the machine for serving a control plane.",
46-
InheritFlags: append(getControlPlanePreparePhaseFlags(),
47-
options.CertificateKey,
48-
),
44+
Name: "all",
45+
Short: "Prepares the machine for serving a control plane.",
46+
InheritFlags: getControlPlanePreparePhaseFlags("all"),
4947
RunAllSiblings: true,
5048
},
5149
newControlPlanePrepareDownloadCertsSubphase(),
@@ -56,58 +54,66 @@ func NewControlPlanePreparePhase() workflow.Phase {
5654
}
5755
}
5856

59-
func getControlPlanePreparePhaseFlags() []string {
60-
return []string{
57+
func getControlPlanePreparePhaseFlags(name string) []string {
58+
flags := []string{
6159
options.APIServerAdvertiseAddress,
6260
options.APIServerBindPort,
6361
options.CfgPath,
6462
options.ControlPlane,
6563
options.NodeName,
66-
options.FileDiscovery,
67-
options.TokenDiscovery,
68-
options.TokenDiscoveryCAHash,
69-
options.TokenDiscoverySkipCAHash,
70-
options.TLSBootstrapToken,
71-
options.TokenStr,
7264
}
65+
if name != "manifests" {
66+
flags = append(flags,
67+
options.FileDiscovery,
68+
options.TokenDiscovery,
69+
options.TokenDiscoveryCAHash,
70+
options.TokenDiscoverySkipCAHash,
71+
options.TLSBootstrapToken,
72+
options.TokenStr,
73+
)
74+
}
75+
if name == "all" || name == "download-certs" {
76+
flags = append(flags,
77+
options.CertificateKey,
78+
)
79+
}
80+
return flags
7381
}
7482

7583
func newControlPlanePrepareDownloadCertsSubphase() workflow.Phase {
7684
return workflow.Phase{
77-
Name: "download-certs",
78-
Short: fmt.Sprintf("Download certificates from %s", kubeadmconstants.KubeadmCertsSecret),
79-
Long: cmdutil.MacroCommandLongDescription,
80-
Run: runControlPlanePrepareDownloadCertsPhaseLocal,
81-
InheritFlags: append(getControlPlanePreparePhaseFlags(),
82-
options.CertificateKey,
83-
),
85+
Name: "download-certs",
86+
Short: fmt.Sprintf("Download certificates from %s", kubeadmconstants.KubeadmCertsSecret),
87+
Long: cmdutil.MacroCommandLongDescription,
88+
Run: runControlPlanePrepareDownloadCertsPhaseLocal,
89+
InheritFlags: getControlPlanePreparePhaseFlags("download-certs"),
8490
}
8591
}
8692

8793
func newControlPlanePrepareCertsSubphase() workflow.Phase {
8894
return workflow.Phase{
8995
Name: "certs",
9096
Short: "Generates the certificates for the new control plane components",
91-
Run: runControlPlanePrepareCertsPhaseLocal,
92-
InheritFlags: getControlPlanePreparePhaseFlags(), //NB. eventually in future we would like to break down this in sub phases for each cert or add the --csr option
97+
Run: runControlPlanePrepareCertsPhaseLocal, //NB. eventually in future we would like to break down this in sub phases for each cert or add the --csr option
98+
InheritFlags: getControlPlanePreparePhaseFlags("certs"),
9399
}
94100
}
95101

96102
func newControlPlanePrepareKubeconfigSubphase() workflow.Phase {
97103
return workflow.Phase{
98104
Name: "kubeconfig",
99105
Short: "Generates the kubeconfig for the new control plane components",
100-
Run: runControlPlanePrepareKubeconfigPhaseLocal,
101-
InheritFlags: getControlPlanePreparePhaseFlags(), //NB. eventually in future we would like to break down this in sub phases for each kubeconfig
106+
Run: runControlPlanePrepareKubeconfigPhaseLocal, //NB. eventually in future we would like to break down this in sub phases for each kubeconfig
107+
InheritFlags: getControlPlanePreparePhaseFlags("kubeconfig"),
102108
}
103109
}
104110

105111
func newControlPlanePrepareManifestsSubphases() workflow.Phase {
106112
return workflow.Phase{
107113
Name: "manifests",
108114
Short: "Generates the manifests for the new control plane components",
109-
Run: runControlPlanePrepareManifestsSubphase,
110-
InheritFlags: getControlPlanePreparePhaseFlags(), //NB. eventually in future we would like to break down this in sub phases for each component
115+
Run: runControlPlanePrepareManifestsSubphase, //NB. eventually in future we would like to break down this in sub phases for each component
116+
InheritFlags: getControlPlanePreparePhaseFlags("manifests"),
111117
}
112118
}
113119

0 commit comments

Comments
 (0)