バイナリ名を変更した時のKubectlのコマンド補完の導入


概要

現在、私はkubernetesをDocker for Macのものを使用していますが、
最新版を入れてみたいなと思ったためkubectlの最新版をインストールしました。

その際、コマンド補完を導入したのですが、kubectlのバイナリ名を変えた際に、
コマンド補完の試行錯誤したため、その内容についてまとめます。
私はzshを使用しており、bashでの導入は未確認のため、zshでの導入についてのみ記述します。

kubernetesのインストール

最新版のkubernetesはcurlにてダウンロードできます。
内容は公式ドキュメントをざっくり訳しただけです。
https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-using-curl

# バイナリのダウンロード
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl

# バイナリを実行できるように権限の変更
chmod +x ./kubectl

# PATHの通ってるディレクトリにファイルを移動
sudo mv ./kubectl /usr/local/bin/kubectl

特定のバージョンをインストールしたい場合は、上記コマンドの$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)部をv1.14.0のようにバージョンに置き換えることで特定のバージョンをインストールできます。

1.14.0をMacOSにインストールしたい場合
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.14.0/bin/darwin/amd64/kubectl

kubectlのコマンド補完導入

bashの場合は、bash-completionを導入しないといけないようですが、
zshに関しては以下を実行してsource <(kubectl completion zsh)を.zshrcに追記するだけです。
実行後はシェルを再起動するとコマンド補完が機能するようになります。

echo "source <(kubectl completion zsh)" >> ~/.zshrc

もし、complete:13: command not found: compdefのようなエラーが出る場合は、
.zshrcの先頭に以下を追記してください。

.zshrc
autoload -Uz compinit
compinit

kubectlのバイナリ名を変更したい場合

kubectlはクラスタのkubernetesのバージョンに対して1マイナーバージョン以下のものを使用するように求められています。
つまり、クラスタのバージョンがv1.11の場合、v1.10, v1.11, v1.12のkubectlが使用できるわけです。
そのため、複数のバージョンのクラスタを利用している場合、複数のkubectlをインストールすることがありえます。
その際、バイナリ名をkubectl-1.14.1のように変更して、バイナリを保存する場合があると思います。
今回は、この場合でのkubectl-1.14.1に対するコマンド補完の導入についてお話しします。

1. コマンド補完用のシェルスクリプトの生成

まず、上述のkubectl completion zshコマンドを利用して、コマンド補完用のシェルスクリプトを生成します。
この際、必ずコマンド補完を導入したいバイナリで実行してください。

kubectl-1.14.1 completion zsh > ./kubectl-1.14.1_completion.sh

2. 生成したシェルスクリプトの修正

生成したシェルスクリプトのkubectlkubectl-1.14.1に置換します。
その際、以下の点に気をつけてください。

  • __kubectl_override_flag_listは関数ではなく、変数のため置換しないでください
    • kubectl-1.14.1のようにピリオドが入るとコマンドと認識されるためエラーになります

3. .zshrcにシェルスクリプトを追記

以下を実行して、.zshrcにシェルスクリプトを読み込むよう追記しましょう。
これでシェルを再起動すると、バイナリ名を変更したコマンドにもコマンド補完が反映されます。

ホームに保存した場合
echo "source ~/kubectl-1.14.1_completion.sh" >> ~/.zshrc

あとがき

自分の環境でバイナリ名を変更したものにもコマンド補完効かせたいなと思い試行錯誤してみました。
自分がシェルスクリプトに慣れていないために、変数__kubectl_override_flag_listで、
変数にピリオドを使用するとコマンドと認識されてしまうと知らなくて、數十分ハマってしまいました。
他にも同じことをしたい、同じところでハマる(笑)人がいると思ったので、まとめてみました。
皆さんの助けになれれば幸いです。

compdef初めて触ったので、何か間違ってる箇所があればご指摘のほど、よろしくお願いいたします。

後記

結局、バイナリは一箇所に集約して、つどつど/usr/local/binのシンボリックリンクを張り替えることにしました(笑)
その結果、シェル起動した際に張り替えた方のバイナリが呼ばれるので、source <(kubectl completion zsh)だけでよくなりました。