————————————————
type Options struct {//version结构体 ClientOnly bool Short bool Output string discoveryClient discovery.CachedDiscoveryInterface genericclioptions.IOStreams }
func NewOptions(ioStreams genericclioptions.IOStreams) *Options { return &Options{//初始化结构体 IOStreams: ioStreams, } } // NewCmdVersion returns a cobra command for fetching versions //创建version命令 func NewCmdVersion(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewOptions(ioStreams)//初始化结构体 cmd := &cobra.Command{//创建cobra命令 Use: "version", Short: i18n.T("Print the client and server version information"), Long: "Print the client and server version information for the current context", Example: versionExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd))//准备 cmdutil.CheckErr(o.Validate())//校验 cmdutil.CheckErr(o.Run())//运行 }, } cmd.Flags().BoolVar(&o.ClientOnly, "client", o.ClientOnly, "Client version only (no server required).")//client选项 cmd.Flags().BoolVar(&o.Short, "short", o.Short, "Print just the version number.")//short选项 cmd.Flags().StringVarP(&o.Output, "output", "o", o.Output, "One of 'yaml' or 'json'.")//output选项 return cmd }
//准备 func (o *Options) Complete(f cmdutil.Factory, cmd *cobra.Command) error { var err error if o.ClientOnly {//如果指定client,返回 return nil } o.discoveryClient, err = f.ToDiscoveryClient()//设置discoveryClient // if we had an empty rest.Config, continue and just print out client information. // if we had an error other than being unable to build a rest.Config, fail. if err != nil && !clientcmd.IsEmptyConfig(err) { return err } return nil } // Validate validates the provided options func (o *Options) Validate() error {//校验 if o.Output != "" && o.Output != "yaml" && o.Output != "json" {//输出格式必须是空,yaml或json return errors.New(`--output must be 'yaml' or 'json'`) } return nil }
//运行 func (o *Options) Run() error { var ( serverVersion *apimachineryversion.Info serverErr error versionInfo Version ) clientVersion := version.Get()//获取客户端版本 versionInfo.ClientVersion = &clientVersion//设置versionInfo if !o.ClientOnly && o.discoveryClient != nil {//如果非clientonly // Always request fresh data from the server o.discoveryClient.Invalidate()//使缓存失效 serverVersion, serverErr = o.discoveryClient.ServerVersion()//获取服务端版本 versionInfo.ServerVersion = serverVersion//设置versionInfo } switch o.Output {//判断输出格式 case "":// 如果是空 if o.Short {//如果指定了short fmt.Fprintf(o.Out, "Client Version: %s\n", clientVersion.GitVersion)//打印client版本 if serverVersion != nil { fmt.Fprintf(o.Out, "Server Version: %s\n", serverVersion.GitVersion)//打印服务端版本 } } else { fmt.Fprintf(o.Out, "Client Version: %s\n", fmt.Sprintf("%#v", clientVersion))//打印client版本 if serverVersion != nil { fmt.Fprintf(o.Out, "Server Version: %s\n", fmt.Sprintf("%#v", *serverVersion))//打印服务端版本 } } case "yaml"://如果是yaml marshalled, err := yaml.Marshal(&versionInfo)//把obj转成yaml if err != nil { return err } fmt.Fprintln(o.Out, string(marshalled))//打印yaml case "json"://如果是json marshalled, err := json.MarshalIndent(&versionInfo, "", " ")//把obj转成json if err != nil { return err } fmt.Fprintln(o.Out, string(marshalled))//打印json default: // There is a bug in the program if we hit this case. // However, we follow a policy of never panicking. return fmt.Errorf("VersionOptions were not validated: --output=%q should have been rejected", o.Output)//报错 } return serverErr }