Cobra+go实现kubectl插件一、cobra

注:个人简单记录
复制代码

一、cobra 简介

cobra是一个命令行程序库,可以用来编写命令行程序。同时,它也提供了一个脚手架, 用于生成基于 cobra 的应用程序框架。

1.1 基本概念

Cobar构建在命令、参数、标志上。

  • Commands:代表的是动作。是程序的核心。程序的交互都包含在Commands中,命令包含子命令。
  • Arguments:代表参数
  • flags:动作的标识符,是修饰命令行为的方式。可以定义一直保留到子命令的标志和仅可用于该命令的标志。

遵循的模式是:

# APPNAME VERB NOUN --ADJECTIVE
# APPNAME COMMAND ARG --FLAG
复制代码

二、示例

2.1 kubectl插件开发

1、创建一个示例的项目,比如说开发一个单独查询pod使用镜像的kubectl插件。

# 创建一个项目目录,例如命名为kubectl-image
# 初始化项目
# go mod init github.com/kubectl-image

# 使用goland开发的打开项目后直接在terminal的执行初始化操作等。
复制代码

2、安装cobra和初始化

# 配置代理
go get -u github.com/spf13/cobra/cobra

# 初始化cobra的cli应用的脚手架。
cobra init --pkg-name 模块名称
复制代码

初始化完成后提供了一个基本的cli应用,项目的基本结构

PROJECT_NAME
|--cmd
|  --root.go
|--pkg
|--go.mod
|--main.go  //cli的入口
复制代码
  • cmd/root.go,这里使用cobra初始rootcmd结构,cli种的所有命令都是root的子命令。root可以理解为根命令,例如go run,go命令就是根命令。示例如下:可以对注释和说明进行修改。
var rootCmd = &cobra.Command{
	Use:   "pods-image",
	Short: "Query the image version used by pods",
	Long: `kubectl can only use describe to query pods details to determine the mirror version, and build a subcommand to query the mirror version of pods`,
	// Uncomment the following line if your bare application
	// has an action associated with it:
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("Query the image version used by pods")
	},
}
复制代码
# 初始化操作
func init() {
   //initConfig初始化的函数
   cobra.OnInitialize(initConfig)

   // Here you will define your flags and configuration settings.
   // Cobra supports persistent flags, which, if defined here,
   // will be global for your application.
   //全局的flags,PersistentFlags就是全局的,可以在当前和该命令的子命令中使用。
   rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.pods-image.yaml)")

   // Cobra also supports local flags, which will only run
   // when this action is called directly.
   //rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

复制代码

3、添加一个命令

# 项目根目录下执行cobra add XXX,比如我们要添加一个get命令,执行之后再cmd package下多个一个文件get.go
]# cobra add get 
复制代码

命令功能开发,run里面执行的匿名函数参数相关:

  • args:这里包含的可以接受的除了-和--参数之外的参数,例如:cobra get image,get是命令,image就属于args。
  • cmd.Flags().GetString("namespace"),这个命令是获取flag参数的值,例如--namespace default,这里获取到的值就是defult.
package cmd

import (
   "fmt"
   "github.com/pods-image/pkg"
   "github.com/spf13/cobra"
   "os"
)

// getCmd represents the get command
var getCmd = &cobra.Command{
   Use:   "get",
   Short: "Get fields in pods details",
   Long:  `There are many fields in pods details, get the details of one of them`,
   // 命令执行的具体函数,定义自己的一些方法,刚开始学比较low
   Run: func(cmd *cobra.Command, args []string) {
      if len(args) == 0 { 
         fmt.Println("Args Error,acceptable parameters: [`image`]")
         cmd.Help()
         os.Exit(1)
      }
      namespace, podname := "default", ""
      if argsValue, err := cmd.Flags().GetString("namespace"); err == nil && argsValue != "" {
         namespace = argsValue
      }
      if len(args) == 2 {
         podname = args[1]
      }
      imageObject := pkg.ImageArgs{
         NameSpace: namespace,
         PodName:   podname,
      }

      switch {
      case args[0] == "image":
         err := pkg.Image(imageObject)
         if err != nil {
            fmt.Println(err)
         }
      case args[0] == "deployment":
         fmt.Println("deployment")
      default:
         cmd.Help()
         os.Exit(1)
      }
   },
}

func init() {
   rootCmd.AddCommand(getCmd) //命令注册到根上
   //定义了一个--namespace/-n的参数,尽在当前命令中生效。
   getCmd.Flags().StringP("namespace", "n", "", "Get the mirror list of the pod")

   // Here you will define your flags and configuration settings.

   // Cobra supports Persistent Flags which will work for this command
   // and all subcommands, e.g.:
   //getCmd.PersistentFlags().String("foo", "", "A help for foo")

   // Cobra supports local flags which will only run when this command
   // is called directly, e.g.:
   // getCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
复制代码

2.2 安装插件到kubectl中

1、把开发好的程序打包

# go build
复制代码

2、上次到kubect所在的机器,把程序名称重命名成kubectl-xxx,并拷贝到系统环境变量所在目录比如/usr/bin/,xxx就代表插件在kubectl子命令的名称,所以不要和现有的冲突。

# 例如:
[root@xxxx ~]# ll /usr/bin/kubectl-images 
-rwxr-xr-x 1 root root 41867691 Dec  2 18:53 /usr/bin/kubectl-images
复制代码

3、测试

# kubectl images get image 
复制代码

不带--namespace默认查询default下的pod
image.png

命令提示

image.png

查询指定namespace下的
image.png