Berbagi teknologi

k8s belajar pembelajaran perpustakaan perintah kobra

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1. Perkenalan

Ketika saya membuka kode k8s, saya menemukan bahwa pada dasarnya layanan inti menggunakan perpustakaan cobra sebagai kemampuan pemrosesan baris perintah.Oleh karena itu, untuk memahami lebih dalam tentang pembelajaran kode di balik kode, pertama-tama mari kita tulis demo berdasarkan pustaka ini untuk memperdalam pemahaman kita tentang pustaka ini.

2. Pengenalan dasar perpustakaan kobra

Github:GitHub - spf13/cobra: Komandan untuk interaksi Go CLI modern Ini dia, Cobra adalah alat baris perintah yang diimplementasikan dalam bahasa Go. Dan sekarang digunakan oleh banyak proyek, seperti Kubernetes, Hugo dan Github CLI, dll.Dengan menggunakan Cobra, kita dapat dengan cepat membuat alat baris perintah, yang sangat cocok untuk menulis测试脚本, berbagai layanan Admin CLITunggu.

Karena parameter baris perintah, golang sendiri dilengkapi dengan pustaka "flag". Bagaimana cara menggunakan pustaka flag?

  1. flag.Parse()
  2. args := flag.Args()

Setelah penguraian, setiap perintah perlu dinilai, yang sangat merepotkan.

Namun saat kita menggunakannya, kita perlu melakukan berbagai analisis dan penilaian pada baris perintah, namun dengan pustaka ini, kita dapat mengurangi kode yang berlebihan ini.

3 Demo penggunaan Cobra

Tanpa basa-basi lagi langsung saja kita jelaskan cara menggunakan project ini. Lingkungan saya menggunakan Macos.

3.1 Pertama-tama unduh perpustakaan yang bergantung

Eksekusi baris perintah

go get -u github.com/spf13/cobra@latest
3.2 Alat CLI baris perintah
$ go install github.com/spf13/cobra-cli@latest

Karena saya sudah membangun direktori bin di jalur kode golang saya, jadi setelah menjalankan perintah ini adalah sebagai berikut

Kami melihat file cobra-cli yang dapat dieksekusi.

Di sini kita dapat menggunakan hal ini dalam perintah untuk menginisialisasinya.Langkah kolektifnya adalah sebagai berikut

  1. xxx@MBP src % mkdir greet
  2. xxx@MBP src % cd greet
  3. xxx@MBP test % ls
  4. xxx@MBP greet % cobra-cli init
  5. Error: Please run `go mod init <MODNAME>` before `cobra-cli init`
  6. xxx@MBP greet % go mod init greet
  7. go: creating new go.mod: module greet
  8. xxx@MBP greet % ls
  9. go.mod
  10. xxx@MBP greet % cobra-cli init
  11. Your Cobra application is ready at
  12. /Users/XXX/workspace/golang/src/greet
  13. xxx@MBP greet % ls
  14. LICENSE cmd go.mod go.sum main.go
  15. xxx@MBP greet %

Langkah pertama adalah membuat direktori test, lalu jalankan go mod init test, lalu jalankan baris perintah cobra-cli init, dan file scaffolding akan dihasilkan.

File-file berikut akan dihasilkan di direktori:

  1. main.go cmd LICENSE go.mod go.sum
  2. ├── LICENSE
  3. ├── cmd
  4. │   └── root.go
  5. └── main.go
  6. go.mod
  7.   go.sum

3.3 Menulis file kode

File yang baru dibuat mungkin tidak banyak berguna karena tidak ada opsi perintah khusus, jadi kami terus mengeksekusi dan menambahkan kata perintah

cobra-cli add [command]

Dengan cara ini, dia akan menghasilkan file lain.

Misalnya, jalankan

cobra-cli tambahkan salam

  1. // Package cmd /*
  2. package cmd
  3. import (
  4. "fmt"
  5. "github.com/spf13/cobra"
  6. )
  7. // greetCmd represents the greet command
  8. var greetCmd = &cobra.Command{
  9. Use:   "greet",
  10. Short: "A brief description of your command",
  11. Long: `A longer description that spans multiple lines and likely contains examples
  12. and usage of using your command. For example:
  13. Cobra is a CLI library for Go that empowers applications.
  14. This application is a tool to generate the needed files
  15. to quickly create a Cobra application.`,
  16. Run: func(cmd *cobra.Command, args []string) {
  17.  // 这段代码是我加的。
  18. if len(args) < 1 {
  19. cmd.Help()
  20. return
  21. }
  22. name := args[0]
  23. fmt.Println("greet called:", name)
  24. },
  25. }
  26. func init() {
  27. rootCmd.AddCommand(greetCmd)
  28. // Here you will define your flags and configuration settings.
  29. // Cobra supports Persistent Flags which will work for this command
  30. // and all subcommands, e.g.:
  31. // greetCmd.PersistentFlags().String("foo", "", "A help for foo")
  32. // Cobra supports local flags which will only run when this command
  33. // is called directly, e.g.:
  34. greetCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
  35. }

Oleh karena itu, kita dapat melihat bahwa perintah salam telah ditambahkan.

Kemudian kami mengkompilasinya dan menghasilkan file target, lalu kami menjalankan yang berikut ini

  1. ./greet
  2. A longer description that spans multiple lines and likely contains
  3. examples and usage of using your application. For example:
  4. Cobra is a CLI library for Go that empowers applications.
  5. This application is a tool to generate the needed files
  6. to quickly create a Cobra application.
  7. Usage:
  8. greet [command]
  9. Available Commands:
  10. completion Generate the autocompletion script for the specified shell
  11. greet       A brief description of your command
  12. help       Help about any command
  13. mockMsg     A brief description of your command
  14. Flags:
  15.  -h, --help     help for greet
  16.  -t, --toggle   Help message for toggle
  17. Use "greet [command] --help" for more information about a command.
 

Dari konten yang dikembalikan di atas, kita dapat melihat bahwa ada subperintah gree tambahan.

Dan Anda dapat menambahkan flag, seperti -h

Run diatas dapat berisi logika bisnis yang ingin kita proses.

Jika kita ingin menambahkan beberapa nilai flag, kita hanya perlu menambahkan kode berikut saat dijalankan

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

Misalnya, kami menerapkan hal berikut:

  1. Run: func(cmd *cobra.Command, args []string) {
  2. if len(args) < 1 {
  3. cmd.Help()
  4. return
  5. }
  6. name := args[0]
  7. fmt.Println("greet called:", name)
  8. g, _ := cmd.Flags().GetInt32("goroutine")
  9. p, _ := cmd.Flags().GetInt32("packet")
  10. fmt.Println("mockmsg called,flags:g=", g, ",p=", p, ",args:", args)
  11. },

Dengan cara ini, bisa digunakan seperti ini

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

4 Cara menggunakannya di K8s

Saya terutama melihat kode modul kubctl, dan saya menemukan bahwa modul ini memiliki enkapsulasi cmd yang lebih kaya untuk mendukung skenario yang lebih kompleks.

Diantaranya, kita mulai dari yang utama kubectl

sebuah metode masuk

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

Karena kubectl dapat memproses file dan flag, berbagai parameter perlu diatur untuk situasi ini. Kami menemukan bahwa setiap kolom dalam struktur cmd telah dimanfaatkan sepenuhnya.

Kedua metode ini adalah metode inti, yang pada dasarnya diinisialisasi dan ditugaskan ke struktur perintah.

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

Diantaranya, NewKubectlCommand digunakan untuk instance cmd baru.

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

Di sinilah kita melihat penggunaan perintah kubectl. Karena artikel ini terutama membahas tentang penggunaan perintah, kami tidak akan membahas detail tentang perintah get lainnya di k8s.

Di bawah ini adalah penjelasan rinci tentang bidang Komando terkait secara spesifik.

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

5 Ringkasan

Artikel ini terutama merupakan penjelasan langkah demi langkah tentang cara menggunakan perpustakaan cobra. Saat kita menggunakan perpustakaan ini, kita dapat lebih memahami prinsip kerjanya, dan kemudian berdasarkan cara menggunakan k8 tertentu dan penggunaan bidang tertentu. memberikan permainan penuh pada kemampuan dan nilai cmd