Kubeadm phases - add local flags

This commit is contained in:
fabriziopandini 2018-11-14 20:29:52 +01:00
parent ba7d3c3ba8
commit 1b9986b219
14 changed files with 109 additions and 71 deletions

View File

@ -155,7 +155,7 @@ func NewCmdInit(out io.Writer) *cobra.Command {
// defines additional flag that are not used by the init command but that could be eventually used // defines additional flag that are not used by the init command but that could be eventually used
// by the sub-commands automatically generated for phases // by the sub-commands automatically generated for phases
initRunner.SetPhaseSubcommandsAdditionalFlags(func(flags *flag.FlagSet) { initRunner.SetAdditionalFlags(func(flags *flag.FlagSet) {
options.AddImageMetaFlags(flags, &initOptions.externalcfg.ImageRepository) options.AddImageMetaFlags(flags, &initOptions.externalcfg.ImageRepository)
options.AddKubeConfigFlag(flags, &initOptions.kubeconfigPath) options.AddKubeConfigFlag(flags, &initOptions.kubeconfigPath)
options.AddKubeConfigDirFlag(flags, &initOptions.kubeconfigDir) options.AddKubeConfigDirFlag(flags, &initOptions.kubeconfigDir)

View File

@ -49,20 +49,20 @@ func NewAddonPhase() workflow.Phase {
return workflow.Phase{ return workflow.Phase{
Name: "addon", Name: "addon",
Short: "Installs required addons for passing Conformance tests", Short: "Installs required addons for passing Conformance tests",
CmdFlags: getAddonPhaseFlags("all"), InheritFlags: getAddonPhaseFlags("all"),
Phases: []workflow.Phase{ Phases: []workflow.Phase{
{ {
Name: "coredns", Name: "coredns",
Short: "Installs the CoreDNS addon to a Kubernetes cluster", Short: "Installs the CoreDNS addon to a Kubernetes cluster",
Long: coreDNSAddonLongDesc, Long: coreDNSAddonLongDesc,
CmdFlags: getAddonPhaseFlags("coredns"), InheritFlags: getAddonPhaseFlags("coredns"),
Run: runCoreDNSAddon, Run: runCoreDNSAddon,
}, },
{ {
Name: "kube-proxy", Name: "kube-proxy",
Short: "Installs the kube-proxy addon to a Kubernetes cluster", Short: "Installs the kube-proxy addon to a Kubernetes cluster",
Long: kubeProxyAddonLongDesc, Long: kubeProxyAddonLongDesc,
CmdFlags: getAddonPhaseFlags("kube-proxy"), InheritFlags: getAddonPhaseFlags("kube-proxy"),
Run: runKubeProxyAddon, Run: runKubeProxyAddon,
}, },
}, },

View File

@ -64,7 +64,7 @@ func NewBootstrapTokenPhase() workflow.Phase {
Short: "Generates bootstrap tokens used to join a node to a cluster", Short: "Generates bootstrap tokens used to join a node to a cluster",
Example: bootstrapTokenExamples, Example: bootstrapTokenExamples,
Long: bootstrapTokenLongDesc, Long: bootstrapTokenLongDesc,
CmdFlags: []string{ InheritFlags: []string{
options.CfgPath, options.CfgPath,
options.KubeconfigDir, options.KubeconfigDir,
options.SkipTokenPrint, options.SkipTokenPrint,

View File

@ -64,7 +64,7 @@ func NewCertsPhase() workflow.Phase {
Short: "Certificate generation", Short: "Certificate generation",
Phases: newCertSubPhases(), Phases: newCertSubPhases(),
Run: runCerts, Run: runCerts,
CmdFlags: getCertPhaseFlags("all"), InheritFlags: getCertPhaseFlags("all"),
} }
} }
@ -108,7 +108,7 @@ func newCertSubPhase(certSpec *certsphase.KubeadmCert, run func(c workflow.RunDa
getSANDescription(certSpec), getSANDescription(certSpec),
), ),
Run: run, Run: run,
CmdFlags: getCertPhaseFlags(certSpec.Name), InheritFlags: getCertPhaseFlags(certSpec.Name),
} }
return phase return phase
} }

View File

@ -78,7 +78,7 @@ func NewControlPlanePhase() workflow.Phase {
newControlPlaneSubPhase(kubeadmconstants.KubeScheduler), newControlPlaneSubPhase(kubeadmconstants.KubeScheduler),
}, },
Run: runControlPlanePhase, Run: runControlPlanePhase,
CmdFlags: getControlPlanePhaseFlags("all"), InheritFlags: getControlPlanePhaseFlags("all"),
} }
return phase return phase
} }
@ -88,7 +88,7 @@ func newControlPlaneSubPhase(component string) workflow.Phase {
Name: controlPlanePhaseProperties[component].name, Name: controlPlanePhaseProperties[component].name,
Short: controlPlanePhaseProperties[component].short, Short: controlPlanePhaseProperties[component].short,
Run: runControlPlaneSubPhase(component), Run: runControlPlaneSubPhase(component),
CmdFlags: getControlPlanePhaseFlags(component), InheritFlags: getControlPlanePhaseFlags(component),
} }
return phase return phase
} }

View File

@ -54,7 +54,7 @@ func NewEtcdPhase() workflow.Phase {
Phases: []workflow.Phase{ Phases: []workflow.Phase{
newEtcdLocalSubPhase(), newEtcdLocalSubPhase(),
}, },
CmdFlags: getEtcdPhaseFlags(), InheritFlags: getEtcdPhaseFlags(),
} }
return phase return phase
} }
@ -65,7 +65,7 @@ func newEtcdLocalSubPhase() workflow.Phase {
Short: "Generates the static Pod manifest file for a local, single-node local etcd instance.", Short: "Generates the static Pod manifest file for a local, single-node local etcd instance.",
Example: etcdLocalExample, Example: etcdLocalExample,
Run: runEtcdPhaseLocal(), Run: runEtcdPhaseLocal(),
CmdFlags: getEtcdPhaseFlags(), InheritFlags: getEtcdPhaseFlags(),
} }
return phase return phase
} }

View File

@ -84,7 +84,7 @@ func NewKubeConfigPhase() workflow.Phase {
NewKubeConfigFilePhase(kubeadmconstants.SchedulerKubeConfigFileName), NewKubeConfigFilePhase(kubeadmconstants.SchedulerKubeConfigFileName),
}, },
Run: runKubeConfig, Run: runKubeConfig,
CmdFlags: getKubeConfigPhaseFlags("all"), InheritFlags: getKubeConfigPhaseFlags("all"),
} }
} }
@ -95,7 +95,7 @@ func NewKubeConfigFilePhase(kubeConfigFileName string) workflow.Phase {
Short: kubeconfigFilePhaseProperties[kubeConfigFileName].short, Short: kubeconfigFilePhaseProperties[kubeConfigFileName].short,
Long: fmt.Sprintf(kubeconfigFilePhaseProperties[kubeConfigFileName].long, kubeConfigFileName), Long: fmt.Sprintf(kubeconfigFilePhaseProperties[kubeConfigFileName].long, kubeConfigFileName),
Run: runKubeConfigFile(kubeConfigFileName), Run: runKubeConfigFile(kubeConfigFileName),
CmdFlags: getKubeConfigPhaseFlags(kubeConfigFileName), InheritFlags: getKubeConfigPhaseFlags(kubeConfigFileName),
} }
} }

View File

@ -50,7 +50,7 @@ func NewKubeletStartPhase() workflow.Phase {
Long: "Writes a file with KubeletConfiguration and an environment file with node specific kubelet settings, and then (re)starts kubelet.", Long: "Writes a file with KubeletConfiguration and an environment file with node specific kubelet settings, and then (re)starts kubelet.",
Example: kubeletStartPhaseExample, Example: kubeletStartPhaseExample,
Run: runKubeletStart, Run: runKubeletStart,
CmdFlags: []string{ InheritFlags: []string{
options.CfgPath, options.CfgPath,
options.NodeCRISocket, options.NodeCRISocket,
options.NodeName, options.NodeName,

View File

@ -48,7 +48,7 @@ func NewMarkControlPlanePhase() workflow.Phase {
Name: "mark-control-plane", Name: "mark-control-plane",
Short: "Mark a node as a control-plane", Short: "Mark a node as a control-plane",
Example: markControlPlaneExample, Example: markControlPlaneExample,
CmdFlags: []string{ InheritFlags: []string{
options.NodeName, options.NodeName,
}, },
Run: runMarkControlPlane, Run: runMarkControlPlane,

View File

@ -53,7 +53,7 @@ func NewPreflightMasterPhase() workflow.Phase {
Long: "Run master pre-flight checks, functionally equivalent to what implemented by kubeadm init.", Long: "Run master pre-flight checks, functionally equivalent to what implemented by kubeadm init.",
Example: masterPreflightExample, Example: masterPreflightExample,
Run: runPreflightMaster, Run: runPreflightMaster,
CmdFlags: []string{ InheritFlags: []string{
options.CfgPath, options.CfgPath,
options.IgnorePreflightErrors, options.IgnorePreflightErrors,
}, },

View File

@ -77,7 +77,7 @@ func NewUploadConfigPhase() workflow.Phase {
Long: uploadKubeadmConfigLongDesc, Long: uploadKubeadmConfigLongDesc,
Example: uploadKubeadmConfigExample, Example: uploadKubeadmConfigExample,
Run: runUploadKubeadmConfig, Run: runUploadKubeadmConfig,
CmdFlags: getUploadConfigPhaseFlags(), InheritFlags: getUploadConfigPhaseFlags(),
}, },
{ {
Name: "kubelet", Name: "kubelet",
@ -85,7 +85,7 @@ func NewUploadConfigPhase() workflow.Phase {
Long: uploadKubeletConfigLongDesc, Long: uploadKubeletConfigLongDesc,
Example: uploadKubeletConfigExample, Example: uploadKubeletConfigExample,
Run: runUploadKubeletConfig, Run: runUploadKubeletConfig,
CmdFlags: getUploadConfigPhaseFlags(), InheritFlags: getUploadConfigPhaseFlags(),
}, },
}, },
} }

View File

@ -16,6 +16,8 @@ limitations under the License.
package workflow package workflow
import "github.com/spf13/pflag"
// Phase provides an implementation of a workflow phase that allows // Phase provides an implementation of a workflow phase that allows
// creation of new phases by simply instantiating a variable of this type. // creation of new phases by simply instantiating a variable of this type.
type Phase struct { type Phase struct {
@ -53,11 +55,17 @@ type Phase struct {
// If this function return nil, the phase action is always executed. // If this function return nil, the phase action is always executed.
RunIf func(data RunData) (bool, error) RunIf func(data RunData) (bool, error)
// CmdFlags defines the list of flags that should be assigned to the cobra command generated // InheritFlags defines the list of flags that the cobra command generated for this phase should Inherit
// for this phase; flags are inherited from the parent command or defined as additional flags // from local flags defined in the parent command / or additional flags defined in the phase runner.
// in the phase runner. If the values is not set or empty, no flags will be assigned to the command // If the values is not set or empty, no flags will be assigned to the command
// Nb. global flags are automatically inherited by nested cobra command // Nb. global flags are automatically inherited by nested cobra command
CmdFlags []string InheritFlags []string
// LocalFlags defines the list of flags that should be assigned to the cobra command generated
// for this phase.
// Nb. if two or phases have the same local flags, please consider using local flags in the parent command
// or additional flags defined in the phase runner.
LocalFlags *pflag.FlagSet
} }
// AppendPhase adds the given phase to the nested, ordered sequence of phases. // AppendPhase adds the given phase to the nested, ordered sequence of phases.

View File

@ -60,8 +60,8 @@ type Runner struct {
// more than one time) // more than one time)
runData RunData runData RunData
// cmdAdditionalFlags holds additional flags that could be added to the subcommands generated // cmdAdditionalFlags holds additional, shared flags that could be added to the subcommands generated
// for each phase. Flags could be inherited from the parent command too // for phases. Flags could be inherited from the parent command too or added directly to each phase
cmdAdditionalFlags *pflag.FlagSet cmdAdditionalFlags *pflag.FlagSet
// phaseRunners is part of the internal state of the runner and provides // phaseRunners is part of the internal state of the runner and provides
@ -269,10 +269,11 @@ func (e *Runner) Help(cmdUse string) string {
return line return line
} }
// SetPhaseSubcommandsAdditionalFlags allows to define flags to be added // SetAdditionalFlags allows to define flags to be added
// to the subcommands generated for each phase (but not existing in the parent command). // to the subcommands generated for each phase (but not existing in the parent command).
// Please note that this command needs to be done before BindToCommand. // Please note that this command needs to be done before BindToCommand.
func (e *Runner) SetPhaseSubcommandsAdditionalFlags(fn func(*pflag.FlagSet)) { // Nb. if a flag is used only by one phase, please consider using phase LocalFlags.
func (e *Runner) SetAdditionalFlags(fn func(*pflag.FlagSet)) {
// creates a new NewFlagSet // creates a new NewFlagSet
e.cmdAdditionalFlags = pflag.NewFlagSet("phaseAdditionalFlags", pflag.ContinueOnError) e.cmdAdditionalFlags = pflag.NewFlagSet("phaseAdditionalFlags", pflag.ContinueOnError)
// invokes the function that sets additional flags // invokes the function that sets additional flags
@ -325,11 +326,18 @@ func (e *Runner) BindToCommand(cmd *cobra.Command) {
// makes the new command inherits local flags from the parent command // makes the new command inherits local flags from the parent command
// Nb. global flags will be inherited automatically // Nb. global flags will be inherited automatically
inheritsFlags(cmd.Flags(), phaseCmd.Flags(), p.CmdFlags) inheritsFlags(cmd.Flags(), phaseCmd.Flags(), p.InheritFlags)
// If defined, additional flags for phases should be added as well // makes the new command inherits additional flags for phases
if e.cmdAdditionalFlags != nil { if e.cmdAdditionalFlags != nil {
inheritsFlags(e.cmdAdditionalFlags, phaseCmd.Flags(), p.CmdFlags) inheritsFlags(e.cmdAdditionalFlags, phaseCmd.Flags(), p.InheritFlags)
}
// If defined, added phase local flags
if p.LocalFlags != nil {
p.LocalFlags.VisitAll(func(f *pflag.Flag) {
phaseCmd.Flags().AddFlag(f)
})
} }
// adds the command to parent // adds the command to parent

View File

@ -286,12 +286,23 @@ func phaseBuilder4(name string, cmdFlags []string, phases ...Phase) Phase {
return Phase{ return Phase{
Name: name, Name: name,
Phases: phases, Phases: phases,
CmdFlags: cmdFlags, InheritFlags: cmdFlags,
}
}
func phaseBuilder5(name string, flags *pflag.FlagSet) Phase {
return Phase{
Name: name,
LocalFlags: flags,
} }
} }
func TestBindToCommand(t *testing.T) { func TestBindToCommand(t *testing.T) {
var dummy string
localFlags := pflag.NewFlagSet("dummy", pflag.ContinueOnError)
localFlags.StringVarP(&dummy, "flag4", "d", "d", "d")
var usecases = []struct { var usecases = []struct {
name string name string
runner Runner runner Runner
@ -339,6 +350,15 @@ func TestBindToCommand(t *testing.T) {
"phase baz": {"flag1"}, "phase baz": {"flag1"},
}, },
}, },
{
name: "it should be possible to apply custom flags to single phases",
runner: Runner{
Phases: []Phase{phaseBuilder5("foo", localFlags)},
},
expectedCmdAndFlags: map[string][]string{
"phase foo": {"flag4"},
},
},
{ {
name: "all the above applies to nested phases too", name: "all the above applies to nested phases too",
runner: Runner{ runner: Runner{
@ -346,6 +366,7 @@ func TestBindToCommand(t *testing.T) {
phaseBuilder4("foo", []string{"flag3"}, phaseBuilder4("foo", []string{"flag3"},
phaseBuilder4("bar", []string{"flag1", "flag2", "flag3"}), phaseBuilder4("bar", []string{"flag1", "flag2", "flag3"}),
phaseBuilder4("baz", []string{"flag1"}), //test if additional flags are filtered too phaseBuilder4("baz", []string{"flag1"}), //test if additional flags are filtered too
phaseBuilder5("qux", localFlags),
), ),
}, },
}, },
@ -357,6 +378,7 @@ func TestBindToCommand(t *testing.T) {
"phase foo": {"flag3"}, "phase foo": {"flag3"},
"phase foo bar": {"flag1", "flag2", "flag3"}, "phase foo bar": {"flag1", "flag2", "flag3"},
"phase foo baz": {"flag1"}, "phase foo baz": {"flag1"},
"phase foo qux": {"flag4"},
}, },
}, },
} }
@ -372,7 +394,7 @@ func TestBindToCommand(t *testing.T) {
cmd.Flags().StringVarP(&dummy2, "flag2", "b", "b", "b") cmd.Flags().StringVarP(&dummy2, "flag2", "b", "b", "b")
if rt.setAdditionalFlags != nil { if rt.setAdditionalFlags != nil {
rt.runner.SetPhaseSubcommandsAdditionalFlags(rt.setAdditionalFlags) rt.runner.SetAdditionalFlags(rt.setAdditionalFlags)
} }
rt.runner.BindToCommand(cmd) rt.runner.BindToCommand(cmd)