cobra

1 基本概念

Cobra是Go的CLI框架,它包含一个用于创建强大的现代 CLI 应用程序的库和一个用于快速生成基于 Cobra 的应用程序和命令文件的工具。Cobra基于三个基本概念commands,argumentsflags,其中commands代表行为,arguments代表数值,flags代表对行为的改变,命令使用示例:

APPNAME VERB NOUN --ADJECTIVE
# 或者
APPNAME COMMAND ARG --FLAG

# server是commands,port是flag 
hugo server --port=1313

# clone是commands,URL是arguments,brae是flags
git clone URL --bare


特点: - 简单的基于子命令的 CLI:app serverapp fetch等。 - 完全符合 POSIX 的标志(包括短版和长版)。 - 嵌套子命令。 - 全局、本地和级联标志。 - cobra init appname使用&轻松生成应用程序和命令cobra add cmdname。 - 明智的建议(app srver……你的意思是app server?). - 命令和标志的自动帮助生成。 - -h,--help等的自动帮助标志识别。 - 为您的应用程序自动生成 bash 自动完成功能。 - 为您的应用程序自动生成的手册页。 - 命令别名,这样您就可以在不破坏它们的情况下进行更改。 - 定义您自己的帮助、使用等的灵活性。 - 与viper的可选紧密集成。



2 安装cobra

安装命令:

go get -u github.com/spf13/cobra/cobra

基本目录结构:

▾ appName/
    ▾ cmd/
        root.go
        yourCommand1.go
        yourCommand2.go
      main.go


2.1 人工构建Cobra应用

root.go文件内容如下:

package cmd  
  
import (  
   "github.com/spf13/cobra"
)  
  
var RootCmd = &cobra.Command{  
   Use:                "mpc",  
   Short:              "Manage Prometheus configuration",  
   Long:               `Manage Prometheus configuration`,  
   DisableSuggestions: true,  
   Run: func(cmd *cobra.Command, args []string) {  
      cmd.Traverse(args)  
   },  
}  


man.go文件内容如下:

package main  
  
import (  
   "mpc/cmd"  
   "os"
)  

  
func main() {  
   if err := cmd.RootCmd.Execute(); err != nil {  
      fmt.Println(err)  
      os.Exit(1)  
   }  
}


2.2 使用生成器构建Cobra应用

安装cobra后,在GOPATH文件夹github.com/spf13/cobra/cobra下使用go install$GOPATH/bin路径下生成cobra.exe可执行命令。

# cobra -h

Usage:
  cobra [command]
 
Available Commands:
  add         向Cobra应用程序添加命令
  completion  完成为指定的shell生成自动完成脚本                 
  help        任何命令都需要帮助
  init        初始化Cobra应用程序                                             

Flags: 
  -a, --author string    作者姓名(默认为“您的姓名”)
      --config string    配置文件(默认值为$HOME/.cobra.yaml)
  -h, --help             cobra帮助
  -l, --license string   项目许可证名称
      --viper            使用Viper进行配置
                                                                                          
Use "cobra [command] --help" for more information about a command.


初始化根命令,在当前项目下生成cmd/root.go

cobra init

添加子命令,在当前项目下生成cmd/your_command.go

cobra add



3 使用规则

cobra三大件是commands,argumentsflags,下面介绍三大件用法。

3.1 commands

每个客户端命令都有一个根命令入口,其他子命令在根命令下延申,类似一颗树,例如根命令kubectl,其中一个子命令为kubectl apply

cobra的根命令和子命令的简单示例:

// kubectl根命令
rootCMD := &cobra.Command{  
   Use:           "kubectl",  
   Short:         "kubectl controls the Kubernetes cluster manager.",  
}

// 添加子命令
rootCMD.AddCommand(  
    applyCMD
)


// 一个子命令apply
applyCMD := &cobra.Command{  
   Use:           "apply",  
   Short:         "Apply a configuration to a resource by filename or stdin.", 
   RunE: func(cmd *cobra.Command, args []string) error {  
      // 执行命令逻辑
   }, 
}

cobra.Command对象下有很多属性,下面是一些常用属性设置


(1) 版本

如果在root命令上设置了version字段,Cobra会添加一个顶级的--version标志。运行带有-version标志的应用程序将使用版本模板将版本打印到标准输出。

rootCmd.Version="0.0.1"
// 或自定义版本
rootCmd.SetVersionTemplate("the version is 0.0.1")


(2) 运行前和运行后钩子

可以在命令的主运行函数之前或之后运行函数。PersistentPreRun和PreRun函数在运行之前执行,而PersistentPostRun和PostRun将在运行后执行。如果子函数不声明自己的函数,则它们将继承Persistent*Run函数,这些函数按以下顺序运行:

PersistentPreRun –> PreRun –> Run –> PostRun –> PersistentPostRun

带有错误返回执行顺序

PersistentPreRunE –> PreRunE –> RunE –> PostRunE –> PersistentPostRunE


(3) 发生“未知命令”时的建议

当发生“未知命令”错误时,Cobra将打印自动建议。这使得Cobra在发生拼写错误时的行为类似于git命令,如果不需要在命令中建议或调整字符串距离,可以通过属性禁止。

command.DisableSuggestions = true
command.SuggestionsMinimumDistance = 1


(4) 为命令生成文档

Cobra可以基于子命令、标志等生成文档。请在docs generation文档中阅读更多关于它的信息。


(5) shell补全

Cobra可以为以下shell生成shell完成文件:bash、zsh、fish、PowerShell。如果您在命令中添加更多信息,这些补全功能将非常强大和灵活。在Shell Completions中阅读更多关于它的信息。


3.2 arguments

命令可能有必须的参数,在cobra.Command对象属性下可以对参数进行处理,例如命令后面必须有且只有一个参数,示例代码如下:

rootCMD := &cobra.Command{  
   Use:           "kubectl",  
   Short:         "kubectl controls the Kubernetes cluster manager.",
   Args:          cobra.ExactArgs(1),
}

cobra提供校验参数函数: - NoArgs: 如果存在任何位置参数,该命令将报告错误。 - ArbitraryArgs: 该命令将接受任何args。 - OnlyValidArgs: 如果有任何位置参数不在命令的ValidArgs字段中,则该命令将报告错误。 - MinimumNArgs(int): 如果没有至少N个位置参数,则该命令将报告错误。 - MaximumNArgs(int): 如果位置参数超过N个,则该命令将报告错误。 - ExactArgs(int): 如果没有正好N个位置参数,则命令将报告错误。 - ExactValidArgs(int): 如果没有正好N个位置参数,或者如果有任何位置参数不在命令的ValidArgs字段中,则该命令将报告错误 - RangeArgs(min,max): 如果args的数目不在预期的最小和最大args数目之间,则命令将报告错误。


也可以在cobra.Command对象属性下的Run或RunE进行自定义校验,示例代码:


var resourceNameArg string

applyCMD := &cobra.Command{  
   Use:           "get",  
   Short:         "Display one or many resources.", 
   RunE: func(cmd *cobra.Command, args []string) error {
      if len(args) < 1 {  
         return fmt.Errorf("You must specify the type of resource to get, eg: kubectl get pod")
      }
      resourceArg = args[0]  
      args = args[1:]  

      // 执行命令逻辑
   }, 
}


3.2 flags

flags用来控制操作命令的操作方式。

(1) 本地flags

在本地分配一个flag,该flag只应用于该特定命令。

// flag s只在localCmd上起作用
localCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")

默认情况下,Cobra只解析目标命令上的本地flag,而忽略父命令上的任何本地flags。通过启用Command.TraverseChildren,Cobra将在执行目标命令之前解析每个命令上的本地flags。

command := cobra.Command{
  Use: "print [OPTIONS] [COMMANDS]",
  TraverseChildren: true,
}


(2) 持久flags

flag可以是持久的,这意味着该flag将可用于分配给它的命令以及该命令下的每个命令。对于全局flag,在根上指定一个标志作为持久标志。

// flag v将在rootCmd及以下的子命令上都生效
rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")


(3) 必须的flags

flags默认是可选的,如果希望命令在未设置flag时报告错误。

rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
rootCmd.MarkFlagRequired("region")


(4)viper绑定flags

var author string

func init() {
  rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
  viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
}

在本例中,持久标志author与viper绑定。注意:当用户未提供–author标志时,变量author将不会设置为config中的值。



4 一个完整的cobra使用示例

以一个管理prometheus的配置文件自动化运维工具mpc(https://github.com/zhufuyi/mpc )为例,mpc主要对prometheus.yaml文件的job、targets、labels三个对象增删改查,支持远程安装exporter,命令帮助信息如下:

$ mpc
manage prometheus configuration, add,delete,update job

Usage:
  mpc [command]

Available Commands:
  add         Add job,targets,labels to prometheus configuration file
  completion  Generate the autocompletion script for the specified shell
  delete      Delete job,targets,labels in prometheus configuration file
  exec        Install and run service to one remote server
  execs       Install and run service to multiple remote servers
  get         Show job,targets,labels from prometheus configuration file
  help        Help about any command
  reload      Make the prometheus configuration effective
  replace     Replace job,targets,labels to prometheus configuration file
  resources   List of supported resources

Flags:
  -h, --help      help for mpc
  -v, --version   version for mpc

Use "mpc [command] --help" for more information about a command.


参考:



专题「golang相关」的其它文章 »