k8s学习之cobra命令库学习

news2025/1/11 15:01:06

1.前言

打开k8s代码的时候,我发现基本上那几个核心服务都是使用cobra库作为命令行处理的能力。因此,为了对代码之后的代码学习的有比较深入的理解,因此先基于这个库写个demo,加深对这个库的一些理解吧

2.cobra库的基本简介

Github:GitHub - spf13/cobra: A Commander for modern Go CLI interactions 在这里了,Cobra是一个用Go语言实现的命令行工具。并且现在正在被很多项目使用,例如:Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速的创建命令行工具,特别适合写 测试脚本,各种服务的 Admin CLI等。

因为命令行参数,golang本身自带了"flag" 库,使用flag库呢

flag.Parse()  
​
args := flag.Args()

解析完之后,需要每个命令去判断,十分的麻烦。

但是我们在使用到时候,需要针对命令行进行各种解析判断,但是有了这个库,我们就可以减少这段冗余的代码了

3 cobra的使用demo

话不多说,我们直接给出怎么用这个项目。我的环境是在macos上。

3.1 首先下载依赖库

命令行执行

go get -u github.com/spf13/cobra@latest
3.2 命令行CLI工具
$ go install github.com/spf13/cobra-cli@latest

因为我本身我的golang代码路径已经建好了bin目录,因此,执行完该命令后,如下

我们看到了cobra-cli的可执行文件。

这边是我们可以在命令用这个东西,进行初始化了。集体步骤如下

xxx@MBP src % mkdir greet
xxx@MBP src % cd greet
xxx@MBP test % ls
xxx@MBP greet % cobra-cli init
Error: Please run `go mod init <MODNAME>` before `cobra-cli init`
xxx@MBP greet % go mod init greet
go: creating new go.mod: module greet
xxx@MBP greet % ls
go.mod
xxx@MBP greet % cobra-cli init
Your Cobra application is ready at
/Users/XXX/workspace/golang/src/greet
xxx@MBP greet % ls
LICENSE cmd go.mod  go.sum  main.go
xxx@MBP greet %

第一步先建好一个test目录,然后执行go mod init test,然后再执行cobra-cli init的命令行,就会生成了脚手架文件了。

目录中会产生一下文件:

main.go cmd LICENSE go.mod go.sum
├── LICENSE
├── cmd
│   └── root.go
└── main.go
    go.mod 
    go.sum

3.3 编写代码文件

刚刚生成的文件,因为没有加具体的命令选项,可能用处不大,因此我们继续执行,添加一个命令字

cobra-cli add [command]

这样,他就会又生成了一个文件。

比如执行

cobra-cli add greet

// Package cmd /*
package cmd
​
import (
  "fmt"
​
  "github.com/spf13/cobra"
)
​
// greetCmd represents the greet command
var greetCmd = &cobra.Command{
  Use:   "greet",
  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.`,
  Run: func(cmd *cobra.Command, args []string) {
    // 这段代码是我加的。
    if len(args) < 1 {
      cmd.Help()
      return
    }
    name := args[0]
    fmt.Println("greet called:", name)
  },
}
​
func init() {
  rootCmd.AddCommand(greetCmd)
​
  // Here you will define your flags and configuration settings.
​
  // Cobra supports Persistent Flags which will work for this command
  // and all subcommands, e.g.:
  // greetCmd.PersistentFlags().String("foo", "", "A help for foo")
​
  // Cobra supports local flags which will only run when this command
  // is called directly, e.g.:
  greetCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

因此,我们可以看到,新增了greet的命令。

然后我们编译一下,生成目标文件,后我们执行以下

./greet

A longer description that spans multiple lines and likely contains
examples and usage of using your application. 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.
​
Usage:
  greet [command]
​
Available Commands:
  completion  Generate the autocompletion script for the specified shell
  greet       A brief description of your command
  help        Help about any command
  mockMsg     A brief description of your command
​
Flags:
  -h, --help     help for greet
  -t, --toggle   Help message for toggle
​
Use "greet [command] --help" for more information about a command.
​
 

以上我们通过返回的内容,可以看出多了一个gree的子命令。

并且可以加flag,比如-h

上边的Run 就可以放我们想要处理的业务逻辑了。

如果我们想增加一些flag 值,只需要能够在run里边添加如下代码即可

g, _ := cmd.Flags().GetInt32("goroutine")
 p, _ := cmd.Flags().GetInt32("packet")
 fmt.Println("mockmsg called,flags:g=", g, ",p=", p, ",args:", args)

比如我们实现如下:

Run: func(cmd *cobra.Command, args []string) {
    if len(args) < 1 {
      cmd.Help()
      return
    }
    name := args[0]
    fmt.Println("greet called:", name)
​
    g, _ := cmd.Flags().GetInt32("goroutine")
    p, _ := cmd.Flags().GetInt32("packet")
    fmt.Println("mockmsg called,flags:g=", g, ",p=", p, ",args:", args)
  },

这样,问可以这样使用了

./greet greet xx -p 10 -g 100
greet called: xx
greetCmd called,flags:g= 100 ,p= 10 ,args: [xx]
​

4 K8s中如何使用

我主要是看了kubctl模块的代码,我发现这个模块对cmd这块又进行了更丰富的封装,用以支持更加复杂的场景。

其中我们从kubectl的main开始

一个入口方法

// NewDefaultKubectlCommand creates the `kubectl` command with default arguments
func NewDefaultKubectlCommand() *cobra.Command {
  ioStreams := genericiooptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
  return NewDefaultKubectlCommandWithArgs(KubectlOptions{
    PluginHandler: NewDefaultPluginHandler(plugin.ValidPluginFilenamePrefixes),
    Arguments:     os.Args,
    ConfigFlags:   defaultConfigFlags().WithWarningPrinter(ioStreams),
    IOStreams:     ioStreams,
  })
}

因为kubectl是可以对文件,以及flag进行处理使用的,因此,需要针对这种情况各种设置参数,我们发现已经充分利用了cmd结构体的内各个字段

其中 这两个方法是核心方法,基本上是初始化并赋值给command的结构了

// NewDefaultKubectlCommandWithArgs creates the `kubectl` command with arguments
func NewDefaultKubectlCommandWithArgs(o KubectlOptions) *cobra.Command {
  cmd := NewKubectlCommand(o)

其中在NewKubectlCommand 就是用来new cmd实例的。

func NewKubectlCommand(o KubectlOptions) *cobra.Command {
  warningHandler := rest.NewWarningWriter(o.IOStreams.ErrOut, rest.WarningWriterOptions{Deduplicate: true, Color: term.AllowsColorOutput(o.IOStreams.ErrOut)})
  warningsAsErrors := false
  // Parent command to which all subcommands are added.
  cmds := &cobra.Command{
    Use:   "kubectl",

这个就是 我么看到的kubectl的命令的使用地方了,因为本文主要是讲command的使用,因此k8s的其他get命令等先不赘述,下一篇在讲

下面是具体贴一下Command具体的相关的字段了意思了

以下是对 `Command` 结构体中每个字段的详细解释:
​
1. `Use`:这是一个字符串,用于描述命令的基本使用方式。它规定了命令所需的参数和可选参数的格式,为用户提供了简洁明了的使用指导。
    - 例如:`"add [-F file | -D dir]... [-f format] profile"` 表示 `add` 命令可以有可选的 `-F` 和 `-D` 参数,其中 `-F` 后跟一个文件,`-D` 后跟一个目录,这两个参数是互斥的,并且可以多次出现,还有一个可选的 `-f` 参数后跟格式信息,最后需要一个 `profile` 参数。
​
2. `Aliases`:一个字符串切片,存储了该命令的别名。这使得用户可以通过不同的名称来调用同一个命令,增加了命令使用的灵活性。
    - 比如:`["add_item", "insert"]` 是 `add` 命令的别名。
​
3. `SuggestFor`:也是一个字符串切片,其中包含了此命令可能被建议替代的其他命令名称。这有助于在用户输入类似但不完全准确的命令时提供相关的建议。
​
4. `Short`:一个简短的字符串,用于在帮助输出中提供命令的简短描述,让用户快速了解命令的主要功能。
    - 例如:"添加新的项目"
​
5. `GroupID`:指定该子命令在其父命令的“帮助”输出中所属的组标识,便于对命令进行分组展示和管理。
​
6. `Long`:详细的长字符串,在“帮助 <此命令>”输出中提供更全面和深入的命令描述,包括更多的功能细节、使用示例、注意事项等。
​
7. `Example`:包含命令使用的示例字符串,通过实际的例子帮助用户更好地理解如何正确使用该命令。
​
8. `ValidArgs`:一个字符串切片,列出了在外壳自动补全中所有有效的非标志参数。
​
9. `ValidArgsFunction`:一个函数,动态地提供有效的非标志参数用于外壳自动补全,是一种更灵活的参数提供方式。
​
10. `Args`:定义了预期的参数的相关规则和处理方式。
​
11. `ArgAliases`:一个字符串切片,列出了有效参数的别名,这些别名不会在外壳自动补全中被提示,但手动输入时会被接受。
​
12. `BashCompletionFunction`:用于传统 Bash 自动补全生成器的自定义 Bash 函数,为特定的 Bash 环境提供定制的自动补全功能。
​
13. `Deprecated`:如果命令已被弃用,存储了使用该命令时将显示的提示信息,告知用户该命令不应再被使用。
​
14. `Annotations`:一个键值对映射,允许应用程序为命令添加自定义的标识、分组或特殊选项等元数据。
​
15. `Version`:存储命令的版本信息,用于版本控制和显示。
​
16. 各种 `Run` 函数:
    - `PersistentPreRun` 和 `PersistentPreRunE`:在命令执行前被调用,且子命令会继承并执行,用于进行一些持久的预处理操作。
    - `PreRun` 和 `PreRunE`:在命令执行前被调用,但子命令不会继承,用于特定于当前命令的预处理。
    - `Run` 和 `RunE`:实际的工作函数,实现命令的主要逻辑。
    - `PostRun` 和 `PostRunE`:在 `Run` 函数执行后被调用,用于进行后续的处理操作。
​
17. `commandgroups`:一个指针切片,指向子命令所属的组对象。
​
18. `args`:实际从标志解析得到的参数切片。
​
19. `flagErrorBuf`:一个字节缓冲区,用于存储来自 `pflag` 的错误消息。
​
20. `flags`:一个 `flag.FlagSet` 对象,包含了所有的标志。
​
21. `pflags`:存储持久的标志。
​
22. `lflags`:本地标志的缓存,用于优化 `LocalFlags` 函数调用。
​
23. `iflags`:继承的标志的缓存,用于优化相关函数调用。
​
24. `parentsPflags`:父命令的所有持久标志。
​
25. `globNormFunc`:一个全局的标准化函数,用于处理标志名称的标准化。
​
26. `usageFunc`:用户定义的使用函数,用于自定义命令的使用说明。
​
27. `usageTemplate`:用户定义的使用模板。
​
28. `flagErrorFunc`:用户定义的标志错误处理函数。
​
29. `helpTemplate`:用户定义的帮助模板。
​
30. `helpFunc`:用户定义的帮助函数。
​
31. `helpCommand`:具有“帮助”用途的命令,如果用户未定义,则使用默认的帮助命令。
​
32. `helpCommandGroupID`:帮助命令所属的组标识。
​
33. `completionCommandGroupID`:自动完成命令所属的组标识。
​
34. `versionTemplate`:用户定义的版本模板。
​
35. `errPrefix`:用户定义的错误消息前缀。
​
36. `inReader`:用户定义的输入读取器,替代标准输入。
​
37. `outWriter`:用户定义的输出写入器,替代标准输出。
​
38. `errWriter`:用户定义的错误输出写入器,替代标准错误输出。
​
39. `FParseErrWhitelist`:要忽略的标志解析错误的列表。
​
40. `CompletionOptions`:用于控制外壳自动完成的选项。
​
41. `commandsAreSorted`:一个布尔值,指示命令切片是否已排序。
​
42. `commandCalledAs`:一个结构体,记录命令被调用时的名称和是否被调用的状态。
​
43. `ctx`:上下文对象,用于传递和管理命令执行的上下文信息。
​
44. `commands`:一个指针切片,包含此命令支持的子命令。
​
45. `parent`:指向该命令的父命令的指针。
​
46. `Max lengths` 相关字段:记录命令相关字符串的最大长度,用于格式化和展示。
​
47. `TraverseChildren`:一个布尔值,决定是否在执行子命令之前解析所有父命令的标志。
​
48. `Hidden`:如果为真,该命令将在可用命令列表中隐藏,不向用户显示。
​
49. `SilenceErrors`:一个布尔值,用于控制是否静默处理错误。
​
50. `SilenceUsage`:一个布尔值,用于控制在发生错误时是否静默使用信息。
​
51. `DisableFlagParsing`:如果为真,将禁用标志解析,所有标志将作为参数传递给命令。
​
52. `DisableAutoGenTag`:如果为真,在生成文档时将禁用自动生成的标签。
​
53. `DisableFlagsInUseLine`:如果为真,将在使用行中禁用标志的添加。
​
54. `DisableSuggestions`:如果为真,将禁用基于编辑距离的建议功能。
​
55. `SuggestionsMinimumDistance`:定义显示建议的最小编辑距离,必须大于 0 。

5 总结

本篇文章主要是一步步的吧cobra这个库如何使用等进行了详细的解释,我们在使用这个库的时候,比较能够理解他工作的原理,然后再根据具体的k8s如何使用以及具体字段的使用来充分发挥cmd的能力和价值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1905079.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《昇思 25 天学习打卡营第 11 天 | ResNet50 图像分类 》

《昇思 25 天学习打卡营第 11 天 | ResNet50 图像分类 》 活动地址&#xff1a;https://xihe.mindspore.cn/events/mindspore-training-camp 签名&#xff1a;Sam9029 计算机视觉-图像分类&#xff0c;很感兴趣 且今日精神颇佳&#xff0c;一个字&#xff0c;学啊 上一节&…

张量分解(1)——初探张量

&#x1f345; 写在前面 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;这里是hyk写算法了吗&#xff0c;一枚致力于学习算法和人工智能领域的小菜鸟。 &#x1f50e;个人主页&#xff1a;主页链接&#xff08;欢迎各位大佬光临指导&#xff09; ⭐️近…

MybatisPlus实现插入/修改数据自动设置时间

引言 插入数据时自动设置当前时间&#xff0c;更新数据时自动修改日期为修改时的日期。 使用MybatisPlus的扩展接口MetaObjectHandler 步骤 实现接口 实体类加注解 实现接口 package com.example.vueelementson.common;import com.baomidou.mybatisplus.core.handlers.M…

GraalVM上的多语言混合开发

上篇文件我们介绍了GraalVM强大的静态编译功能,能够让Java应用程序摆脱虚拟机的束缚,像其它本地编译的应用一样直接运行。那么GraalVM的神奇之处仅限于此吗?今天我们再来看看它的另一个重要特性—多语言混合开发 多语言平台 Java并不是唯一运行在JVM上的语言,这个我们都应…

Qt/C++音视频开发78-获取本地摄像头支持的分辨率/帧率/格式等信息/mjpeg/yuyv/h264

一、前言 上一篇文章讲到用ffmpeg命令方式执行打印到日志输出&#xff0c;可以拿到本地摄像头设备信息&#xff0c;顺藤摸瓜&#xff0c;发现可以通过执行 ffmpeg -f dshow -list_options true -i video“Webcam” 命令获取指定摄像头设备的分辨率帧率格式等信息&#xff0c;会…

ts-01.泛型(函数和接口)

泛型 泛的意思是:漂浮, 比如泛舟; 泛型: 类型漂浮未定 > 动态类型. 用于: 函数 接口 类 T extends string | number 泛型约束 function a<T any, K> (: number, value: T) { // 泛型参数设置默认值anyconst arr Array<T>(l).fill(value) // [foo, foo, foo] }…

IntelliJ IDEA菜单不见了设置找回方法

通过CtrAltS键按出设置 找到View,然后自定义一个快捷键,然后保存 使用自定义快捷键弹出改界面,点击Main Menu即可

树莓派4B_OpenCv学习笔记19:OpenCV舵机云台物体追踪

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; Python 版本3.7.3&#xff1a; ​​ 今日学习&#xff1…

# 三 JS的流程控制和函数

三 JS的流程控制和函数 3.1 JS分支结构 if结构 这里的if结构几乎和JAVA中的一样,需要注意的是 if()中的非空字符串会被认为是trueif()中的非零数字会被认为是true 代码 if(false){// 非空字符串 if判断为trueconsole.log(true) }else{console.log(false) } if(){// 长度为0…

Linux系统(Centos)下MySQL数据库中文乱码问题解决

问题描述&#xff1a;在进行数据库使用过程中&#xff0c;数据库里的数据中文都显示乱码。操作数据库的时候&#xff0c;会出现中文乱码问题。 解决方法如下&#xff1a; 第一步&#xff1a;打开虚拟机进入系统&#xff0c;启动MySQL。 第二步&#xff1a;连接登录MySQL输入…

排序 -- 万能测试oj

. - 力扣&#xff08;LeetCode&#xff09; 这道题我们可以使用我们学过的那些常见的排序方法来进行解答 //插入排序 void InsertSort(int* nums, int n) {for (int i 0; i < n-1; i){int end i;int tmp nums[end 1];while (end > 0){if (tmp < nums[end]){nums[…

GuitarPro2024音乐软件#创作神器#音乐梦想

嘿&#xff0c;亲爱的朋友们&#xff01;&#x1f44b;&#x1f44b;&#x1f44b;今天我要给你们安利一款超赞的软件——Guitar Pro。这款软件简直是吉他手的福音啊&#xff01;&#x1f389;&#x1f389;&#x1f389; Guitar Pro免费绿色永久安装包下载&#xff1a;&#…

数据结构(其一)--基础知识篇

1. 数据结构三要素 1.1 数据结构的运算 即&#xff0c;增删改查 1.2 数据结构的存储结构 2. 数据类型&#xff0c;抽象数据类型 数据类型&#xff1a; &#xff08;1&#xff09;. 原子类型&#xff1a;bool、int... &#xff08;2&#xff09;. 结构类型&#xff1a;类、…

赤壁之战的烽火台 - 观察者模式

“当烽火连三月&#xff0c;家书抵万金&#xff1b;设计模式得其法&#xff0c;千军如一心。” 在波澜壮阔的三国历史长河中&#xff0c;赤壁之战无疑是一场改变乾坤的重要战役。而在这场战役中&#xff0c;一个看似简单却至关重要的系统发挥了巨大作用——烽火台。这个古老的…

LeetCode 算法:二叉树中的最大路径和 c++

原题链接&#x1f517;&#xff1a;二叉树中的最大路径和 难度&#xff1a;困难⭐️⭐️⭐️ 题目 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;…

赋值运算符重载和const成员函数和 const函数

文章目录 1.运算符重载(1)(2)运算符重载的语法&#xff1a;(3)运算符重载的注意事项&#xff1a;(4)前置和后置重载区别 2.const成员函数3.取地址及const取地址操作符重载4.总结 1.运算符重载 (1) 我们知道内置类型(整形&#xff0c;字符型&#xff0c;浮点型…)可以进行一系…

ImportError: DLL load failed while importing _imaging: 操作系统无法运行 %1

解决方案&#xff1a; &#xff08;1&#xff09;搜索打开Anaconda Prompt控制台&#xff0c;进入到自己要安装的环境下面去&#xff0c;卸载Pillow:pip uninstall Pillow 没有安装Pillow的就不用卸载&#xff0c;直接安装&#xff0c; &#xff08;2&#xff09;然后再安装&a…

入门PHP就来我这(高级)13 ~ 图书添加功能

有胆量你就来跟着路老师卷起来&#xff01; -- 纯干货&#xff0c;技术知识分享 路老师给大家分享PHP语言的知识了&#xff0c;旨在想让大家入门PHP&#xff0c;并深入了解PHP语言。 今天给大家接着上篇文章编写图书添加功能。 1 添加页面 创建add.html页面样式&#xff0c;废…

实验2 Aprori关联挖掘算法

目 录 一、实验目的... 1 二、实验环境... 1 三、实验内容... 1 3.1 connect_string()函数解析... 1 3.2 find_rule()函数解析纠错... 2 3.3 关联规则挖掘... 4 四、心得体会... 7 一、实验目的 &#xff08;1&#xff09;理解Aprori关联挖掘算法的程序编写&#xff1b; &…

《ClipCap》论文笔记(上)

原文出处 [2111.09734] ClipCap: CLIP Prefix for Image Captioning (arxiv.org) 原文笔记 What ClipCap&#xff1a; CLIP Prefix for Image Captioning 一言以蔽之&#xff1a;使用 CLIP 编码作为标题的前缀&#xff0c;使用简单的映射网络&#xff0c;然后微调语言模型…