diff --git a/cmd/kubeadm/app/cmd/join.go b/cmd/kubeadm/app/cmd/join.go index 9818def3ee6..09e926a44fc 100644 --- a/cmd/kubeadm/app/cmd/join.go +++ b/cmd/kubeadm/app/cmd/join.go @@ -157,7 +157,7 @@ func NewCmdJoin(out io.Writer, joinOptions *joinOptions) *cobra.Command { joinRunner := workflow.NewRunner() cmd := &cobra.Command{ - Use: "join", + Use: "join [api-server-endpoint]", Short: "Run this on any machine you wish to join an existing cluster", Long: joinLongDescription, Run: func(cmd *cobra.Command, args []string) { @@ -336,7 +336,7 @@ func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Wri opt.externalcfg.Discovery.BootstrapToken = nil } else { if len(opt.cfgPath) == 0 && len(args) > 1 { - klog.Warningf("[join] WARNING: More than one API server endpoint supplied on command line %v. Using the first one.", args) + klog.Warningf("[preflight] WARNING: More than one API server endpoint supplied on command line %v. Using the first one.", args) } opt.externalcfg.Discovery.BootstrapToken.APIServerEndpoint = args[0] } @@ -352,7 +352,7 @@ func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Wri var tlsBootstrapCfg *clientcmdapi.Config if _, err := os.Stat(adminKubeConfigPath); err == nil && opt.controlPlane { // use the admin.conf as tlsBootstrapCfg, that is the kubeconfig file used for reading the kubeadm-config during discovery - klog.V(1).Infof("[join] found %s. Use it for skipping discovery", adminKubeConfigPath) + klog.V(1).Infof("[preflight] found %s. Use it for skipping discovery", adminKubeConfigPath) tlsBootstrapCfg, err = clientcmd.LoadFromFile(adminKubeConfigPath) if err != nil { return nil, errors.Wrapf(err, "Error loading %s", adminKubeConfigPath) @@ -371,11 +371,11 @@ func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Wri // Either use the config file if specified, or convert public kubeadm API to the internal JoinConfiguration // and validates JoinConfiguration if opt.externalcfg.NodeRegistration.Name == "" { - klog.V(1).Infoln("[join] found NodeName empty; using OS hostname as NodeName") + klog.V(1).Infoln("[preflight] found NodeName empty; using OS hostname as NodeName") } if opt.externalcfg.ControlPlane != nil && opt.externalcfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress == "" { - klog.V(1).Infoln("[join] found advertiseAddress empty; using default interface's IP address as advertiseAddress") + klog.V(1).Infoln("[preflight] found advertiseAddress empty; using default interface's IP address as advertiseAddress") } // in case the command doesn't have flags for discovery, makes the join cfg validation pass checks on discovery @@ -383,7 +383,7 @@ func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Wri if _, err := os.Stat(adminKubeConfigPath); os.IsNotExist(err) { return nil, errors.Errorf("File %s does not exists. Please use 'kubeadm join phase control-plane-prepare' subcommands to generate it.", adminKubeConfigPath) } - klog.V(1).Infof("[join] found discovery flags missing for this command. using FileDiscovery: %s", adminKubeConfigPath) + klog.V(1).Infof("[preflight] found discovery flags missing for this command. using FileDiscovery: %s", adminKubeConfigPath) opt.externalcfg.Discovery.File = &kubeadmapiv1beta1.FileDiscovery{KubeConfigPath: adminKubeConfigPath} 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 ) } @@ -431,7 +431,7 @@ func (j *joinData) TLSBootstrapCfg() (*clientcmdapi.Config, error) { if j.tlsBootstrapCfg != nil { return j.tlsBootstrapCfg, nil } - klog.V(1).Infoln("[join] Discovering cluster-info") + klog.V(1).Infoln("[preflight] Discovering cluster-info") tlsBootstrapCfg, err := discovery.For(j.cfg) j.tlsBootstrapCfg = tlsBootstrapCfg return tlsBootstrapCfg, err @@ -445,7 +445,7 @@ func (j *joinData) InitCfg() (*kubeadmapi.InitConfiguration, error) { if _, err := j.TLSBootstrapCfg(); err != nil { return nil, err } - klog.V(1).Infoln("[join] Fetching init configuration") + klog.V(1).Infoln("[preflight] Fetching init configuration") initCfg, err := fetchInitConfigurationFromJoinConfiguration(j.cfg, j.tlsBootstrapCfg) j.initCfg = initCfg return initCfg, err @@ -459,7 +459,7 @@ func (j *joinData) ClientSet() (*clientset.Clientset, error) { path := kubeadmconstants.GetAdminKubeConfigPath() client, err := kubeconfigutil.ClientSetFromFile(path) if err != nil { - return nil, errors.Wrap(err, "[join] couldn't create Kubernetes client") + return nil, errors.Wrap(err, "[preflight] couldn't create Kubernetes client") } j.clientSet = client return client, nil @@ -478,7 +478,7 @@ func (j *joinData) OutputWriter() io.Writer { // fetchInitConfigurationFromJoinConfiguration retrieves the init configuration from a join configuration, performing the discovery func fetchInitConfigurationFromJoinConfiguration(cfg *kubeadmapi.JoinConfiguration, tlsBootstrapCfg *clientcmdapi.Config) (*kubeadmapi.InitConfiguration, error) { // Retrieves the kubeadm configuration - klog.V(1).Infoln("[join] Retrieving KubeConfig objects") + klog.V(1).Infoln("[preflight] Retrieving KubeConfig objects") initConfiguration, err := fetchInitConfiguration(tlsBootstrapCfg) if err != nil { return nil, err @@ -509,7 +509,7 @@ func fetchInitConfiguration(tlsBootstrapCfg *clientcmdapi.Config) (*kubeadmapi.I } // Fetches the init configuration - initConfiguration, err := configutil.FetchInitConfigurationFromCluster(tlsClient, os.Stdout, "join", true) + initConfiguration, err := configutil.FetchInitConfigurationFromCluster(tlsClient, os.Stdout, "preflight", true) if err != nil { return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap") } diff --git a/cmd/kubeadm/app/cmd/phases/join/controlplanejoin.go b/cmd/kubeadm/app/cmd/phases/join/controlplanejoin.go index 3fd6bc82b78..3c10dc78f6a 100644 --- a/cmd/kubeadm/app/cmd/phases/join/controlplanejoin.go +++ b/cmd/kubeadm/app/cmd/phases/join/controlplanejoin.go @@ -62,7 +62,7 @@ func NewControlPlaneJoinPhase() workflow.Phase { RunAllSiblings: true, }, newEtcdLocalSubphase(), - newUploadConfigSubphase(), + newUpdateStatusSubphase(), newMarkControlPlaneSubphase(), }, } @@ -71,17 +71,21 @@ func NewControlPlaneJoinPhase() workflow.Phase { func newEtcdLocalSubphase() workflow.Phase { return workflow.Phase{ Name: "etcd", - Short: "Generates the static Pod manifest file for a local etcd member", + Short: "Add a new local etcd member", Run: runEtcdPhase, InheritFlags: getControlPlaneJoinPhaseFlags(), } } -func newUploadConfigSubphase() workflow.Phase { +func newUpdateStatusSubphase() workflow.Phase { return workflow.Phase{ - Name: "upload-config", - Short: "Upload the currently used configuration to the cluster", - Run: runUploadConfigPhase, + Name: "update-status", + Short: fmt.Sprintf( + "Register the new control-plane node into the %s maintained in the %s ConfigMap", + kubeadmconstants.ClusterStatusConfigMapKey, + kubeadmconstants.KubeadmConfigConfigMap, + ), + Run: runUpdateStatusPhase, InheritFlags: getControlPlaneJoinPhaseFlags(), } } @@ -136,7 +140,7 @@ func runEtcdPhase(c workflow.RunData) error { return nil } -func runUploadConfigPhase(c workflow.RunData) error { +func runUpdateStatusPhase(c workflow.RunData) error { data, ok := c.(JoinData) if !ok { return errors.New("control-plane-join phase invoked with an invalid data struct") diff --git a/cmd/kubeadm/app/cmd/phases/join/controlplaneprepare.go b/cmd/kubeadm/app/cmd/phases/join/controlplaneprepare.go index eae73d2eee8..a83fff95fd6 100644 --- a/cmd/kubeadm/app/cmd/phases/join/controlplaneprepare.go +++ b/cmd/kubeadm/app/cmd/phases/join/controlplaneprepare.go @@ -25,7 +25,6 @@ import ( "k8s.io/klog" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" - cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane" @@ -41,7 +40,7 @@ func NewControlPlanePreparePhase() workflow.Phase { Short: "Prepares the machine for serving a control plane.", Phases: []workflow.Phase{ { - Name: "all", + Name: "all [api-server-endpoint]", Short: "Prepares the machine for serving a control plane.", InheritFlags: getControlPlanePreparePhaseFlags("all"), RunAllSiblings: true, @@ -82,9 +81,8 @@ func getControlPlanePreparePhaseFlags(name string) []string { func newControlPlanePrepareDownloadCertsSubphase() workflow.Phase { return workflow.Phase{ - Name: "download-certs", - Short: fmt.Sprintf("Download certificates from %s", kubeadmconstants.KubeadmCertsSecret), - Long: cmdutil.MacroCommandLongDescription, + Name: "download-certs [api-server-endpoint]", + Short: fmt.Sprintf("[EXPERIMENTAL] Downloads certificates shared among control-plane nodes from the %s Secret", kubeadmconstants.KubeadmCertsSecret), Run: runControlPlanePrepareDownloadCertsPhaseLocal, InheritFlags: getControlPlanePreparePhaseFlags("download-certs"), } @@ -92,7 +90,7 @@ func newControlPlanePrepareDownloadCertsSubphase() workflow.Phase { func newControlPlanePrepareCertsSubphase() workflow.Phase { return workflow.Phase{ - Name: "certs", + Name: "certs [api-server-endpoint]", Short: "Generates the certificates for the new control plane components", Run: runControlPlanePrepareCertsPhaseLocal, //NB. eventually in future we would like to break down this in sub phases for each cert or add the --csr option InheritFlags: getControlPlanePreparePhaseFlags("certs"), @@ -101,7 +99,7 @@ func newControlPlanePrepareCertsSubphase() workflow.Phase { func newControlPlanePrepareKubeconfigSubphase() workflow.Phase { return workflow.Phase{ - Name: "kubeconfig", + Name: "kubeconfig [api-server-endpoint]", Short: "Generates the kubeconfig for the new control plane components", Run: runControlPlanePrepareKubeconfigPhaseLocal, //NB. eventually in future we would like to break down this in sub phases for each kubeconfig InheritFlags: getControlPlanePreparePhaseFlags("kubeconfig"), @@ -110,7 +108,7 @@ func newControlPlanePrepareKubeconfigSubphase() workflow.Phase { func newControlPlanePrepareManifestsSubphases() workflow.Phase { return workflow.Phase{ - Name: "manifests", + Name: "control-plane", Short: "Generates the manifests for the new control plane components", Run: runControlPlanePrepareManifestsSubphase, //NB. eventually in future we would like to break down this in sub phases for each component InheritFlags: getControlPlanePreparePhaseFlags("manifests"), diff --git a/cmd/kubeadm/app/cmd/phases/join/kubelet.go b/cmd/kubeadm/app/cmd/phases/join/kubelet.go index fc7c6903091..65270712b00 100644 --- a/cmd/kubeadm/app/cmd/phases/join/kubelet.go +++ b/cmd/kubeadm/app/cmd/phases/join/kubelet.go @@ -56,7 +56,7 @@ var ( // NewKubeletStartPhase creates a kubeadm workflow phase that start kubelet on a node. func NewKubeletStartPhase() workflow.Phase { return workflow.Phase{ - Name: "kubelet-start", + Name: "kubelet-start [api-server-endpoint]", Short: "Writes kubelet settings, certificates and (re)starts the kubelet", Long: "Writes a file with KubeletConfiguration and an environment file with node specific kubelet settings, and then (re)starts kubelet.", Run: runKubeletStartJoinPhase, @@ -102,7 +102,7 @@ func runKubeletStartJoinPhase(c workflow.RunData) error { bootstrapKubeConfigFile := kubeadmconstants.GetBootstrapKubeletKubeConfigPath() // Write the bootstrap kubelet config file or the TLS-Boostrapped kubelet config file down to disk - klog.V(1).Infoln("[join] writing bootstrap kubelet config file at", bootstrapKubeConfigFile) + klog.V(1).Infoln("[kubelet-start] writing bootstrap kubelet config file at", bootstrapKubeConfigFile) if err := kubeconfigutil.WriteToDisk(bootstrapKubeConfigFile, tlsBootstrapCfg); err != nil { return errors.Wrap(err, "couldn't save bootstrap-kubelet.conf to disk") } diff --git a/cmd/kubeadm/app/cmd/phases/join/preflight.go b/cmd/kubeadm/app/cmd/phases/join/preflight.go index 9f1aa102135..8c49c6f7294 100644 --- a/cmd/kubeadm/app/cmd/phases/join/preflight.go +++ b/cmd/kubeadm/app/cmd/phases/join/preflight.go @@ -54,7 +54,7 @@ var ( // NewPreflightPhase creates a kubeadm workflow phase that implements preflight checks for a new node join func NewPreflightPhase() workflow.Phase { return workflow.Phase{ - Name: "preflight", + Name: "preflight [api-server-endpoint]", Short: "Run join pre-flight checks", Long: "Run pre-flight checks for kubeadm join.", Example: preflightExample, diff --git a/cmd/kubeadm/app/cmd/phases/workflow/runner.go b/cmd/kubeadm/app/cmd/phases/workflow/runner.go index 183c50212b4..7cfc90234b0 100644 --- a/cmd/kubeadm/app/cmd/phases/workflow/runner.go +++ b/cmd/kubeadm/app/cmd/phases/workflow/runner.go @@ -442,8 +442,8 @@ func (e *Runner) prepareForExecution() { // addPhaseRunner adds the phaseRunner for a given phase to the phaseRunners list func addPhaseRunner(e *Runner, parentRunner *phaseRunner, phase Phase) { // computes contextual information derived by the workflow managed by the Runner. - generatedName := strings.ToLower(phase.Name) - use := generatedName + use := cleanName(phase.Name) + generatedName := use selfPath := []string{generatedName} if parentRunner != nil { @@ -471,3 +471,13 @@ func addPhaseRunner(e *Runner, parentRunner *phaseRunner, phase Phase) { addPhaseRunner(e, currentRunner, childPhase) } } + +// cleanName makes phase name suitable for the runner help, by lowercasing the name +// and removing args descriptors, if any +func cleanName(name string) string { + ret := strings.ToLower(name) + if pos := strings.Index(ret, " "); pos != -1 { + ret = ret[:pos] + } + return ret +} diff --git a/cmd/kubeadm/app/cmd/phases/workflow/runner_test.go b/cmd/kubeadm/app/cmd/phases/workflow/runner_test.go index 1b65eb717f4..2e9dcf1c732 100644 --- a/cmd/kubeadm/app/cmd/phases/workflow/runner_test.go +++ b/cmd/kubeadm/app/cmd/phases/workflow/runner_test.go @@ -262,7 +262,7 @@ func TestHelp(t *testing.T) { var w = Runner{ Phases: []Phase{ phaseBuilder3("foo", false, - phaseBuilder3("bar", false), + phaseBuilder3("bar [arg]", false), phaseBuilder3("baz", true), ), phaseBuilder3("qux", false), @@ -272,7 +272,7 @@ func TestHelp(t *testing.T) { expected := "The \"myCommand\" command executes the following phases:\n" + "```\n" + "foo long description for foo ...\n" + - " /bar long description for bar ...\n" + + " /bar long description for bar [arg] ...\n" + "qux long description for qux ...\n" + "```"