cant find main module in 命令行_Kubectl命令行工具拓展实战及源码解析

25e9dee04a7ee19b64d8f3c9fe251380.png

Kubernetes目前支持对Kubectl命令行工具进行拓展,也就是所谓的 kubectl plugins, 具体可以查看官方文档:

Extend kubectl with plugins​kubernetes.io
4c9be44b9be56d1644a05c7ccafb6ae5.png

那么我们就试着来实现一个小的Demo,为了方便,我们就使用官方的实例。

首先实现一个Kubectl Plugin的要求总结如下:

  1. 可执行文件
  2. 名称以kubectl-开头,命令以-来分割,比如kubectl gpu version的可执行文件名称是kubectl-gpu-version。命令名称中如果包含-,用_表示,比如kubectl gpu-version的可执行文件名称是kubectl-gpu_version
  3. 可执行文件位于PATH路径下
  4. 不能和kubectl命令或者子命令重复,比如kubectl version

在实现的时候我们需要注意几点:

  1. Kubectl查找时按照最长匹配原则,比如存在kubectl-gpukubectl-gpu-version,那么输入kubectl gpu verson时执行的是kubectl-gpu-version
  2. 运行命令名称重复,但是只有一个会执行,具体哪个可以通过kubectl plugin list查看
kubectl plugin list
The following kubectl-compatible plugins are available:

/usr/local/bin/plugins/kubectl-foo
/usr/local/bin/moreplugins/kubectl-foo
  - warning: /usr/local/bin/moreplugins/kubectl-foo is overshadowed by a similarly named plugin: /usr/local/bin/plugins/kubectl-foo

error: one plugin warning was found

明确了上面的需求和注意点,我们来写一个脚本文件 kubectl-foo

#!/bin/bash

# optional argument handling
if [[ "$1" == "version" ]]
then
    echo "1.0.0"
    exit 0
fi

# optional argument handling
if [[ "$1" == "config" ]]
then
    echo $KUBECONFIG
    exit 0
fi

echo "I am a plugin named kubectl-foo"

然后一道$PATH目录下:

sudo chmod +x ./kubectl-foo

sudo mv ./kubectl-foo /usr/local/bin

kubectl foo

这样我们就可以看到 "I am a plugin named kubectl-foo"这个结果了。

总体上来说还是很简单的,那么Kubernetes是怎么实现的呢,其实也很简单,就是一个查找过程,源码解析如下:

pkg/kubectl/cmd/cmd.go Line 310
func NewDefaultKubectlCommandWithArgs(pluginHandler PluginHandler, args []string, in io.Reader, out, errout io.Writer) *cobra.Command {
	cmd := NewKubectlCommand(in, out, errout)

	if pluginHandler == nil {
		return cmd
	}

	if len(args) > 1 {
		cmdPathPieces := args[1:]

		if _, _, err := cmd.Find(cmdPathPieces); err != nil { //如果找到Kubectl子命令,直接退出
			if err := HandlePluginCommand(pluginHandler, cmdPathPieces); err != nil { // 查找Plugin命令
				fmt.Fprintf(errout, "%vn", err)
				os.Exit(1)
			}
		}
	}

	return cmd
}
pkg/kubectl/cmd/cmd.go Line 398
func HandlePluginCommand(pluginHandler PluginHandler, cmdArgs []string) error {
	remainingArgs := []string{} // all "non-flag" arguments

	for idx := range cmdArgs {
		if strings.HasPrefix(cmdArgs[idx], "-") { // 跳过flag参数
			break
		}
		remainingArgs = append(remainingArgs, strings.Replace(cmdArgs[idx], "-", "_", -1)) // 替换其中的“-”为_“”
	}

	foundBinaryPath := ""

	// attempt to find binary, starting at longest possible name with given cmdArgs
	for len(remainingArgs) > 0 {
		path, found := pluginHandler.Lookup(strings.Join(remainingArgs, "-")) // 在Path中寻找可执行文件(用-连接)
		if !found {
			remainingArgs = remainingArgs[:len(remainingArgs)-1] // 没找到缩短名称
			continue
		}

		foundBinaryPath = path
		break
	}

	if len(foundBinaryPath) == 0 {
		return nil
	}

	// invoke cmd binary relaying the current environment and args given
	if err := pluginHandler.Execute(foundBinaryPath, cmdArgs[len(remainingArgs):], os.Environ()); err != nil { // 调用Plugin可执行文件
		return err
	}

	return nil
}

关于上面的内容已经放到Github上了,欢迎Star :)

kuberenetes-learning/kubectl-plugin-demo​github.com
66d650cfc6750880490301a52f52407a.png

也欢迎喜欢Kubernetes的一起加入这个小组 :)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值