Golang urfave/cli调用kubectl时如何移除参数多余kubectl前缀
问题根因
出现该错误的核心原因有两个:
cmd.NewDefaultKubectlCommand()返回的是cobra实现的命令,默认会读取全局os.Args作为执行入参。执行myapp kubectl get pods时,os.Args值为["myapp", "kubectl", "get", "pods"],kubectl启动后会将第二个参数kubectl识别为待执行的子命令,自然找不到对应子命令抛出错误。而myapp get pods能正常运行属于巧合:此时os.Args第二个参数是get,刚好是kubectl的内置子命令。- urfave/cli默认会解析所有传入的flag,如果不对子命令做特殊配置,透传kubectl专属flag(比如
--kubeconfig)时,会被urfave/cli拦截报「未知flag」错误,无法正常透传。
修复方案
1. 改造kubectl封装函数
修改pkg/cmds/kubectl.go,让封装函数支持接收自定义参数,不再依赖全局os.Args,同时显式绑定标准输入输出流避免输出异常:
package cmds import ( "os" "k8s.io/component-base/cli" "k8s.io/kubectl/pkg/cmd" "k8s.io/kubectl/pkg/cmd/util" _ "k8s.io/client-go/plugin/pkg/client/auth" ) // Kubectl 接收透传的参数列表,执行原生kubectl逻辑 func Kubectl(args []string) { command := cmd.NewDefaultKubectlCommand() // cobra要求参数切片第一个元素为命令自身名称,因此前缀拼接"kubectl" cmdArgs := append([]string{"kubectl"}, args...) command.SetArgs(cmdArgs) // 显式绑定标准流,避免输出、输入被吞 command.SetIn(os.Stdin) command.SetOut(os.Stdout) command.SetErr(os.Stderr) if err := cli.RunNoErrOutput(command); err != nil { util.CheckErr(err) } }
2. 调整urfave/cli命令配置
修改main.go,给需要透传参数的子命令开启SkipFlagParsing配置,让urfave/cli不解析后续所有参数、flag,全部原样透传,同时调用封装函数时传入正确的参数切片:
package main import ( "log" "os" "github.com/user/repo/pkg/cmds" "github.com/urfave/cli/v2" ) func main() { app := &cli.App{ Commands: []*cli.Command{ { Name: "kubectl", Aliases: []string{"k"}, Usage: "透传所有参数执行原生kubectl", // 跳过flag解析,所有后续内容原样透传 SkipFlagParsing: true, Action: func(cCtx *cli.Context) error { cmds.Kubectl(cCtx.Args().Slice()) return nil }, }, { Name: "get", Aliases: []string{"v"}, Usage: "等价执行kubectl get", // 同样跳过flag解析 SkipFlagParsing: true, Action: func(cCtx *cli.Context) error { // 固定前缀为get,拼接用户传入的后续参数 args := append([]string{"get"}, cCtx.Args().Slice()...) cmds.Kubectl(args) return nil }, }, }, } if err := app.Run(os.Args); err != nil { log.Fatal(err) } }
验证效果
修复后以下命令均可正常执行:
go run . kubectl version:正常输出kubectl版本信息go run . kubectl get pods -n kube-system:正常获取指定命名空间的pod列表,所有kubectl原生flag均可正常透传go run . get pods -n kube-system:等价于执行kubectl get pods -n kube-system,符合预期go run . k get nodes:别名k可正常使用,效果和kubectl子命令完全一致
内容的提问来源于stack exchange,提问作者petrichor256
相关产品推荐
相关产品推荐

