Focus on the target
Our goal is to see how kubectl create -f nginx_pod.yaml works.
directory
-
Main entry
-
Matching of passed arguments with subcommands
-
Initialization of kubectl commands
-
View the create subcommand
-
The creation logic of runCreate
main
func main(a) {
// If you do not call rand.Seed, the rand function returns the same value each time you rerun the main function
// Seed is a random Seed. Each time you use a timestamp as a Seed, randomness is guaranteed
rand.Seed(time.Now().UnixNano())
// create the default parameters of the kubectl command
command := cmd.NewDefaultKubectlCommand()
// TODO: once we switch everything over to Cobra commands, we can go back to calling
// cliflag.InitFlags() (by removing its pflag.Parse() call). For now, we have to set the
// normalize func and add the go flag set by hand.
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
// cliflag.InitFlags()
// Log initialization and exit
logs.InitLogs()
defer logs.FlushLogs()
/ / run the command
iferr := command.Execute(); err ! =nil {
os.Exit(1)}}Copy the code
match
// The k8S command line tool uses cobra library, with command prompt and other powerful functions, much more powerful than the go language flag, please refer to github.com/spf13/cobra
func NewDefaultKubectlCommand(a) *cobra.Command {
return NewDefaultKubectlCommandWithArgs(NewDefaultPluginHandler(plugin.ValidPluginFilenamePrefixes), os.Args, os.Stdin, os.Stdout, os.Stderr)
}
func NewDefaultKubectlCommandWithArgs(pluginHandler PluginHandler, args []string, in io.Reader, out, errout io.Writer) *cobra.Command {
// Initialize NewKubectlCommand with standard input, output, error output
cmd := NewKubectlCommand(in, out, errout)
if pluginHandler == nil {
return cmd
}
if len(args) > 1 {
// Here is the parameter passed, namely the create-f nginx_pod.yaml part
cmdPathPieces := args[1:]
Call COBRA's Find to match args
if_, _, err := cmd.Find(cmdPathPieces); err ! =nil {
iferr := HandlePluginCommand(pluginHandler, cmdPathPieces); err ! =nil {
fmt.Fprintf(errout, "%v\n", err)
os.Exit(1)}}}return cmd
}
Copy the code
command
The code is long, so I’ll pick the key points
func NewKubectlCommand(in io.Reader, out, err io.Writer) *cobra.Command {
warningHandler := rest.NewWarningWriter(err, rest.WarningWriterOptions{Deduplicate: true, Color: term.AllowsColorOutput(err)})
warningsAsErrors := false
// Create the main command
cmds := &cobra.Command{
Use: "kubectl",
Short: i18n.T("kubectl controls the Kubernetes cluster manager"),
Long: templates.LongDesc(` kubectl controls the Kubernetes cluster manager. Find more information at: https://kubernetes.io/docs/reference/kubectl/overview/`),
Run: runHelp,
// After initialization, the hook before running the instruction
PersistentPreRunE: func(*cobra.Command, []string) error {
rest.SetDefaultWarningHandler(warningHandler)
Profile.pprof = profile.pprof = profile.pprof = profile.pprof = profile.pprof = profile.pprof = profile.pprof = profile.pprof
return initProfiling()
},
// Run the hook after the instruction
PersistentPostRunE: func(*cobra.Command, []string) error {
// Save pPROF performance metrics
iferr := flushProfiling(); err ! =nil {
return err
}
// Prints the number of warnings
if warningsAsErrors {
count := warningHandler.WarningCount()
switch count {
case 0:
// no warnings
case 1:
return fmt.Errorf("%d warning received", count)
default:
return fmt.Errorf("%d warnings received", count)
}
}
return nil
},
The kubectl completion bash command is used to view the automatic completion function
Specific installation / / https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion for reference
BashCompletionFunction: bashCompletionFunc,
}
// Instantiate the Factory interface, Factory mode
f := cmdutil.NewFactory(matchVersionKubeConfigFlags)
// omit the instantiated procedure code
Kubectl defines seven classes of commands, combined with Message and the package names of each subcommand
groups := templates.CommandGroups{
{
// 1. Basic commands, including create/expose/run/set
Message: "Basic Commands (Beginner):",
Commands: []*cobra.Command{
create.NewCmdCreate(f, ioStreams),
expose.NewCmdExposeService(f, ioStreams),
run.NewCmdRun(f, ioStreams),
set.NewCmdSet(f, ioStreams),
},
},
{
// 2. Intermediate commands including explain/get/edit/delete
Message: "Basic Commands (Intermediate):",
Commands: []*cobra.Command{
explain.NewCmdExplain("kubectl", f, ioStreams),
get.NewCmdGet("kubectl", f, ioStreams),
edit.NewCmdEdit(f, ioStreams),
delete.NewCmdDelete(f, ioStreams),
},
},
{
// 3. Deploy commands, including rollout/scale/autoscale
Message: "Deploy Commands:",
Commands: []*cobra.Command{
rollout.NewCmdRollout(f, ioStreams),
scale.NewCmdScale(f, ioStreams),
autoscale.NewCmdAutoscale(f, ioStreams),
},
},
{
/ / 4. Cluster management commands, including cerfificate/cluster - info/top/cordon/drain/tapping taint
Message: "Cluster Management Commands:",
Commands: []*cobra.Command{
certificates.NewCmdCertificate(f, ioStreams),
clusterinfo.NewCmdClusterInfo(f, ioStreams),
top.NewCmdTop(f, ioStreams),
drain.NewCmdCordon(f, ioStreams),
drain.NewCmdUncordon(f, ioStreams),
drain.NewCmdDrain(f, ioStreams),
taint.NewCmdTaint(f, ioStreams),
},
},
{
/ / 5. Troubleshooting and debugging, including the describe/logs/attach/exec/port - forward/proxy/cp/auth
Message: "Troubleshooting and Debugging Commands:",
Commands: []*cobra.Command{
describe.NewCmdDescribe("kubectl", f, ioStreams),
logs.NewCmdLogs(f, ioStreams),
attach.NewCmdAttach(f, ioStreams),
cmdexec.NewCmdExec(f, ioStreams),
portforward.NewCmdPortForward(f, ioStreams),
proxy.NewCmdProxy(f, ioStreams),
cp.NewCmdCp(f, ioStreams),
auth.NewCmdAuth(f, ioStreams),
},
},
{
/ / 6. High command, including the diff/apply/patch/replace/wait/convert/kustomize
Message: "Advanced Commands:",
Commands: []*cobra.Command{
diff.NewCmdDiff(f, ioStreams),
apply.NewCmdApply("kubectl", f, ioStreams),
patch.NewCmdPatch(f, ioStreams),
replace.NewCmdReplace(f, ioStreams),
wait.NewCmdWait(f, ioStreams),
convert.NewCmdConvert(f, ioStreams),
kustomize.NewCmdKustomize(ioStreams),
},
},
{
// 7. Set commands, including label, annotate, and completion
Message: "Settings Commands:",
Commands: []*cobra.Command{
label.NewCmdLabel(f, ioStreams),
annotate.NewCmdAnnotate("kubectl", f, ioStreams),
completion.NewCmdCompletion(ioStreams.Out, ""),
},
},
}
groups.Add(cmds)
filters := []string{"options"}
// alpha related subcommand
alpha := cmdpkg.NewCmdAlpha(f, ioStreams)
if! alpha.HasSubCommands() { filters =append(filters, alpha.Name())
}
templates.ActsAsRootCommand(cmds, filters, groups...)
// Code completion is relevant
for name, completion := range bashCompletionFlags {
ifcmds.Flag(name) ! =nil {
if cmds.Flag(name).Annotations == nil {
cmds.Flag(name).Annotations = map[string] []string{}
}
cmds.Flag(name).Annotations[cobra.BashCompCustom] = append(
cmds.Flag(name).Annotations[cobra.BashCompCustom],
completion,
)
}
}
/ / add the rest of the command, including the alpha/config/plugins/version/API - versions/API - resources/options
cmds.AddCommand(alpha)
cmds.AddCommand(cmdconfig.NewCmdConfig(f, clientcmd.NewDefaultPathOptions(), ioStreams))
cmds.AddCommand(plugin.NewCmdPlugin(f, ioStreams))
cmds.AddCommand(version.NewCmdVersion(f, ioStreams))
cmds.AddCommand(apiresources.NewCmdAPIVersions(f, ioStreams))
cmds.AddCommand(apiresources.NewCmdAPIResources(f, ioStreams))
cmds.AddCommand(options.NewCmdOptions(ioStreams.Out))
return cmds
}
Copy the code
create
func NewCmdCreate(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
// Options for the create subcommand
o := NewCreateOptions(ioStreams)
// Description of the create subcommand
cmd := &cobra.Command{
Use: "create -f FILENAME",
DisableFlagsInUseLine: true,
Short: i18n.T("Create a resource from a file or from stdin."),
Long: createLong,
Example: createExample,
// Validate parameters and run
Run: func(cmd *cobra.Command, args []string) {
if cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames, o.FilenameOptions.Kustomize) {
ioStreams.ErrOut.Write([]byte("Error: must specify one of -f and -k\n\n"))
defaultRunFunc := cmdutil.DefaultSubCommandRun(ioStreams.ErrOut)
defaultRunFunc(cmd, args)
return
}
cmdutil.CheckErr(o.Complete(f, cmd))
cmdutil.CheckErr(o.ValidateArgs(cmd, args))
// The core running code logic is RunCreate here
cmdutil.CheckErr(o.RunCreate(f, cmd))
},
}
o.RecordFlags.AddFlags(cmd)
usage := "to use to create the resource"
/ / to join filename option flag - f, save to o.F ilenameOptions. The Filenames, corresponding to the above
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
cmdutil.AddValidateFlags(cmd)
cmd.Flags().BoolVar(&o.EditBeforeCreate, "edit", o.EditBeforeCreate, "Edit the API resource before creating")
cmd.Flags().Bool("windows-line-endings", runtime.GOOS == "windows"."Only relevant if --edit=true. Defaults to the line ending native to your platform.")
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddDryRunFlag(cmd)
cmd.Flags().StringVarP(&o.Selector, "selector"."l", o.Selector, "Selector (label query) to filter on, supports '=', '==', and '! ='.(e.g. -l key1=value1,key2=value2)")
cmd.Flags().StringVar(&o.Raw, "raw", o.Raw, "Raw URI to POST to the server. Uses the transport specified by the kubeconfig file.")
cmdutil.AddFieldManagerFlagVar(cmd, &o.fieldManager, "kubectl-create")
o.PrintFlags.AddFlags(cmd)
// subcommand to create, specifying the create object
cmd.AddCommand(NewCmdCreateNamespace(f, ioStreams))
cmd.AddCommand(NewCmdCreateQuota(f, ioStreams))
cmd.AddCommand(NewCmdCreateSecret(f, ioStreams))
cmd.AddCommand(NewCmdCreateConfigMap(f, ioStreams))
cmd.AddCommand(NewCmdCreateServiceAccount(f, ioStreams))
cmd.AddCommand(NewCmdCreateService(f, ioStreams))
cmd.AddCommand(NewCmdCreateDeployment(f, ioStreams))
cmd.AddCommand(NewCmdCreateClusterRole(f, ioStreams))
cmd.AddCommand(NewCmdCreateClusterRoleBinding(f, ioStreams))
cmd.AddCommand(NewCmdCreateRole(f, ioStreams))
cmd.AddCommand(NewCmdCreateRoleBinding(f, ioStreams))
cmd.AddCommand(NewCmdCreatePodDisruptionBudget(f, ioStreams))
cmd.AddCommand(NewCmdCreatePriorityClass(f, ioStreams))
cmd.AddCommand(NewCmdCreateJob(f, ioStreams))
cmd.AddCommand(NewCmdCreateCronJob(f, ioStreams))
return cmd
}
Copy the code
runCreate
func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
// f is the Factory passed in, which encapsulates the client interacting with Kube-Apiserver
schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"))
iferr ! =nil {
return err
}
cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace()
iferr ! =nil {
return err
}
// Instantiate Builder
r := f.NewBuilder().
Unstructured().
Schema(schema).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
// Visitor is not supported for simple local files, but also for standard input and HTTP/HTTPS
FilenameParam(enforceNamespace, &o.FilenameOptions).
LabelSelectorParam(o.Selector).
Flatten().
Do()
err = r.Err()
iferr ! =nil {
return err
}
count := 0
// Call the visit function to create the resource
err = r.Visit(func(info *resource.Info, err error) error {
// Print the result XXXX created
return o.PrintObj(info.Object)
})
return nil
}
Copy the code
Making: github.com/Junedayday/…
Blog: junes.tech/
Public id: Golangcoding