기술나눔

k8s 학습 코브라 명령 라이브러리 학습

2024-07-12

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

1. 소개

k8s 코드를 열었을 때 기본적으로 핵심 서비스는 코브라 라이브러리를 명령줄 처리 기능으로 사용한다는 것을 알았습니다.따라서 코드 뒤에 숨은 코드 학습에 대해 더 깊이 이해하기 위해 먼저 이 라이브러리를 기반으로 데모를 작성하여 이 라이브러리에 대한 이해를 심화하겠습니다.

2.코브라 라이브러리 기본 소개

Github:GitHub - spf13/cobra: 최신 Go CLI 상호 작용을 위한 Commander Cobra는 Go 언어로 구현된 명령줄 도구입니다. 그리고 현재 Kubernetes, Hugo, Github CLI 등 많은 프로젝트에서 사용되고 있습니다.Cobra를 사용하면 특히 쓰기에 적합한 명령줄 도구를 빠르게 만들 수 있습니다.测试脚本, 다양한 서비스 Admin CLI기다리다.

명령줄 매개변수 때문에 golang 자체에는 "플래그" 라이브러리가 함께 제공됩니다. 플래그 라이브러리를 사용하는 방법은 무엇입니까?

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

구문 분석 후 각 명령을 판단해야 하는데 이는 매우 번거로운 작업입니다.

하지만 사용할 때에는 명령줄에서 다양한 분석과 판단을 해야 하는데, 이 라이브러리를 사용하면 이러한 중복 코드를 줄일 수 있습니다.

3 코브라 사용법 데모

더 이상 고민하지 않고 이 프로젝트를 사용하는 방법을 직접 설명하겠습니다. 내 환경은 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의 실행 파일을 보았습니다.

여기서는 명령에서 이 항목을 사용하여 초기화할 수 있습니다.종합적인 단계는 다음과 같습니다

  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 %

첫 번째 단계는 테스트 디렉토리를 생성한 후 go mod init test를 실행하고 cobra-cli init 명령줄을 실행하면 스캐폴딩 파일이 생성됩니다.

디렉터리에 다음 파일이 생성됩니다.

  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 코드 파일 작성

방금 생성된 파일은 특별한 명령어 옵션이 없기 때문에 별로 활용도가 높지 않을 수 있으므로 계속해서 명령어를 실행하고 추가해 나가도록 하겠습니다.

cobra-cli add [command]

이런 식으로 그는 또 다른 파일을 생성할 것입니다.

예를 들어 다음을 실행합니다.

cobra-cli 추가 인사

  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. }

따라서 Greeting 명령어가 추가된 것을 확인할 수 있습니다.

그런 다음 이를 컴파일하고 대상 파일을 생성한 후 다음을 실행합니다.

  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.
 

위의 반환된 콘텐츠에서 추가 gree 하위 명령이 있음을 알 수 있습니다.

그리고 -h와 같은 플래그를 추가할 수 있습니다.

위의 실행에는 처리하려는 비즈니스 로직이 포함될 수 있습니다.

일부 플래그 값을 추가하려면 실행 시 다음 코드만 추가하면 됩니다.

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

예를 들어 다음을 구현합니다.

  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. },

이런 식으로 다음과 같이 사용할 수 있습니다.

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

4 K8s에서 사용하는 방법

나는 주로 kubctl 모듈의 코드를 살펴보았는데, 이 모듈이 더 복잡한 시나리오를 지원하기 위해 cmd를 더 풍부하게 캡슐화했다는 것을 발견했습니다.

그중 kubectl의 메인부터 시작한다.

입국 방법

  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. }

kubectl은 파일과 플래그를 처리할 수 있기 때문에 이 상황에 맞게 다양한 매개변수를 설정해야 합니다. cmd 구조의 각 필드가 완전히 활용되는 것으로 나타났습니다.

이 두 가지 방법은 기본적으로 초기화되어 명령 구조에 할당되는 핵심 방법입니다.

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

그 중 NewKubectlCommand는 새로운 cmd 인스턴스에 사용됩니다.

  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",

여기에서 kubectl 명령의 사용을 볼 수 있습니다. 이 기사에서는 주로 명령의 사용에 대해 설명하므로 다음 기사에서는 k8s의 다른 get 명령에 대해 자세히 설명하지 않겠습니다.

다음은 Command의 구체적인 관련 분야에 대한 자세한 설명입니다.

以下是对 `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 요약

이 기사는 주로 cobra 라이브러리를 사용하는 방법에 대한 단계별 설명입니다. 이 라이브러리를 사용하면 작동 원리를 더 잘 이해할 수 있으며 특정 k8s 사용 방법과 특정 필드의 사용을 기반으로 합니다. cmd의 기능과 가치를 최대한 활용