Golang 的插件辅助库
一、基础准备
在开始分析源码之前, 我们假设读者已经熟悉 Golang 语言,至少对基本语法、指针、依赖管理 工具 有一定认知 ;下面介绍一下 sample-cli-plugin 这个项目一些基础核心的依赖:
1.1、Cobra 终端库
这是一个强大的 Golang 的 command line interface 库,其支持用非常简单的代码创建出符合 Unix 风格的 cli 程序;甚至官方提供了用于创建 cli 工程脚手架的 cli 命令工具;Cobra 官方 Github 地址 点击这里 ,具体用法请自行 Google,以下只做一个简单的命令定义介绍(docker、kubernetes 终端 cli 都基于这个库)
# 每一个命令(不论是子命令还是主命令)都会是一个 cobra.Command 对象 var lsCmd = &cobra.Command{ // 一些命令帮助文档有关的描述信息 Use: "ls", Short: "A brief description of your command", Long: `A longer description that spans multiple lines and likely contains examples and usage of using your command. For example: Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application.`, // 命令运行时真正执行逻辑,如果需要返回 Error 信息,我们一般设置 RunE Run: func(cmd *cobra.Command, args []string) { fmt.Println("ls called") }, } // 为这个命令添加 flag,比如 `--help`、`-p` // PersistentFlags() 方法添加的 flag 在所有子 command 也会生效 // Cobra 的 command 可以无限级联,比如 `kubectl get pod` 就是在 `kubectl` command 下增加了子 `get` command lsCmd.PersistentFlags().String("foo", "", "A help for foo") // Flags() 方法添加的 flag 仅在直接调用此子命令时生效 lsCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
1.2、vendor 依赖
Godeps/Godeps.jsongodep restorego getgo modgo.mod
二、源码分析
2.1、环境搭建
$GOPATH/src/k8s.io/sample-cli-plugin
2.2、定位核心运行方法
cmdcmd
cmd.NewCmdNamespacerootroot.Executerootrootcmd.NewCmdNamespaceRunRunE
NewCmdNamespaceRunEo.Completeo.Validateo.Run
2.3、NamespaceOptions 结构体
o
oNewNamespaceOptionsNewNamespaceOptionsNamespaceOptions
2.3.1、*genericclioptions.ConfigFlags
configFlags*genericclioptions.ConfigFlags
从这些字段上来看,我们可以暂且模糊的推测出这应该是个基础配置型的字段,负责存储一些全局基本设置,比如 API Server 认证信息等
2.3.2、*api.Context
resultingContextresultingContextName*api.Context
2.3.3、userSpecified*
这几个字段从名字上就可以区分出,他们应该用于存储用户设置的或者说是通过命令行选项输入的一些指定配置信息,比如 Cluster、Context 等
2.3.4、rawConfig
api.Config--namespace~/.kube/config
2.3.5、listNamespaces
--listNewCmdNamespace
2.4、核心处理逻辑
介绍完了结构体的基本属性,最后我们只需要弄明白在核心 Command 方法内运行的这三个核心方法就行了
2.4.1、*NamespaceOptions.Complete
这个方法代码稍微有点多,这里不会对每一行代码都做解释,只要大体明白都在干什么就行了;我们的目的是理解它,后续模仿它创造自己的插件;下面是代码截图
rawConfigrawConfigToRawKubeConfigLoader().RawConfig()
NamespaceClusterContextkubectl ns NS_NAME1 --namespace NS_NAME2NS_NAME1NS_NAME2
153o.resultingContext = api.NewContext()resultingContextNamespace
2.4.2、*NamespaceOptions.Validate
rawConfigCurrentContextkubectl ns NS_NAME1 NS_NAME2
2.4.3、*NamespaceOptions.Run
Run
Runo.setNamespace
setNamespaceclientcmd.ModifyConfigKubernetesclient-go
o.setNamespaceNamespaceforNamespace--listNamespace
三、插件总结
分析完了这个官方的插件,然后想一下自己以后写插件可能的需求,最后对比一下,可以为以后写插件做个总结:
xxxOptionsconfigFlagsrawConfig
Golang 的插件辅助库