fish shellのプロンプトにkubectlのContextとNamespaceを表示させてみた

無いなら作ろう精神
2024.05.25

fish shellのプロンプトにもkubectlのContextとNamespaceを表示させたい

こんにちは、のんピ(@non____97)です。

皆さんはfishのプロンプトにもkubectlのContextとNamespaceを表示させたいなと思ったことはありますか? 私はあります。

kubectlを触っていて「自分が今どのContextを使っていて、どのNamespaceの操作をしているのか」が気になることがあります。kubectl config current-contextkubectxkubensを都度叩けば良いのですが、それすら面倒です。

出来ればターミナルのプロンプトに表示しておきたいです。

そんな時はkube-ps1が便利なようです。

しかし、kube-ps1はbashもしくはzshで動作するツールのようです。私が使っているfish shellでは動かすことはできませんでした。

無いなら作ろう

ということでfish shellのプロンプトにkubectlのContextとNamespaceを表示させるスクリプトを作ってみました。

やってみた

スクリプトの紹介

スクリプトは2つです。

  1. ~/.config/fish/functions/kube_prompt.fish
  2. ~/.config/fish/functions/fish_prompt.fish

~/.config/fish/functions/kube_prompt.fishはkubectlを叩いてContextとNamespaceを取得するスクリプトです。

~/.config/fish/functions/fish_prompt.fishはfish shellがプロンプトを表示するときに実行されるスクリプトです。~/.config/fish/functions/fish_prompt.fishを都度呼び出します。

~/.config/fish/functions/kube_prompt.fishのコードは以下のとおりです。k8sの操作をしていないときに表示されるのは不要だと思うので、kube_prompt_onkube_prompt_offで表示/非表示を切り替えられるようにしています。

~/.config/fish/functions/kube_prompt.fish

# グローバルの環境変数の設定
set -g KUBE_PROMPT_ICON "⎈"                   # プロンプトに表示するアイコン
set -g KUBE_CONFIG_PATH "$HOME/.kube/config"  # kubectlの設定ファイルパス
set -g KUBE_PROMPT_ENABLED                    # プロンプトにkubectlの情報を表示するかのフラグ

# kubectlの設定ファイルパスの確認
function get_kube_config_path
    if set -q KUBECONFIG
        echo $KUBECONFIG
    else if test -f $KUBE_CONFIG_PATH
        echo $KUBE_CONFIG_PATH
    end
end

# 現在のContextとNamespaceの取得
function get_context_and_namespace
    set -l output (kubectl config view \
      --minify \
      --output='jsonpath={..current-context},{..namespace}' 2>/dev/null
    )
    if test $status -ne 0
        return
    end

    set -l context (string split ',' $output)[1]
    set -l namespace (string split ',' $output)[2]

    if test -z "$namespace"
        set namespace "default"
    end

    echo $context $namespace
end

# プロンプトのメッセージの設計
function kube_prompt
    # プロンプトにkubectlの情報を表示するかのフラグが立っているか判断
    if not set -q KUBE_PROMPT_ENABLED
        return
    end

    # kubectlの設定ファイルが存在するかチェック
    set -l config (get_kube_config_path)
    if test ! -f $config
        return
    end

    # 現在のContextとNamespaceの取得
    set -l context_and_namespace (get_context_and_namespace)
    
    # Contextが設定されていない場合
    if test -z "$context_and_namespace"
        echo -n -s "(" \
          (set_color red --bold) "$KUBE_PROMPT_ICON" \
          (set_color normal) " | no context ) "
        return
    end

    # プロンプトに表示するContextとNamespaceの整形
    set -l context (string split " " $context_and_namespace)[1]
    set -l namespace (string split " " $context_and_namespace)[2]

    echo -n -s "(" \
      (set_color brcyan --bold) "$KUBE_PROMPT_ICON" \
      (set_color normal) " | " \
      (set_color brcyan) $context \
      (set_color normal) " : " \
      (set_color brgreen) $namespace \
      (set_color normal) ") "
end

# プロンプトにkubectlの情報を表示する
function kube_prompt_on
    set -g KUBE_PROMPT_ENABLED true
end

# プロンプトにkubectlの情報を非表示する
function kube_prompt_off
    set -e KUBE_PROMPT_ENABLED
end

~/.config/fish/functions/fish_prompt.fishのコードは以下のとおりです。先述のスクリプトを呼び出して、プロンプトに表示させているだけです。

~/.config/fish/functions/fish_prompt.fish

function fish_prompt
    # 他にもプロンプトに表示している情報があれば、ここに記述されている

    # kube_prompt.fishの実行
    set -l kube_prompt (kube_prompt)
    if test -n "$kube_prompt"
        echo -n -s " " $kube_prompt " "
    end
end

動作確認

動作確認をしてみます。

Contextを指定していない状態です。プロンプトにもno contextと表示されています。

no context状態

ContextをRancher Desktop上のk8sクラスターに接続するものに切り替えます。プロンプトにrancher desktopとContext、kube-publicとNamespaceが表示されていますね。

contextの切り替え

Namespaceをkube-systemに切り替えます。プロンプトに表示されるNamespaceもkube-systemに変わりました。

Namespaceの切り替え

プロンプトの表示/非表示を切り替えます。kube_prompt_offすると、プロンプトにContextやNamespaceが表示されなくなり、kube_prompt_onすると再度表示されます。

プロンプト表示の切り替え

ContextをEKSクラスターに接続するものに切り替えます。問題なく動作します。なお、都度EKSクラスターに接続しにいくためかプロンプトを表示するのに1秒ほどかかります。

EKSクラスターのcontextへの切り替え

また、EKSクラスターの操作をしている場合はIAMロールにAssume Role + MFAを使用していると、一次認証情報が切れたタイミングでプロンプトを表示しようとする度にMFAの入力を求められます。

残念なことに、ここでMFAのコードを入力しても正常に受け付けられません。

対処療法的な回避方法としては以下のとおりです。

  • 一度kube_prompt_offでContextとNamespaceをプロンプトから非表示にする
    • プロンプト表示時に都度、裏側でkubectlを叩かなくためMFAコードの入力も促されなくなる
  • Contextのユーザーにてaws sts get-caller-identitykubectl config viewなど適当にAWSのコマンド、もしくは裏側でAWSに認証をしにいくコマンドを叩く
  • MFAコードの入力を求められたら、MFAコードを入力する
  • kube_prompt_onでContextとNamespaceをプロンプトに表示する

一度kube_prompt_offにしてから適当にkubetclのコマンドを叩いてMFAを入力

他の回避方法が見つかったら追記します。

無いなら作ろう精神

fish shellのプロンプトにkubectlのContextとNamespaceを表示させてみました。

無いなら作ろう精神です。EKSクラスターを触る時はプロンプトの描画が遅いのが気になりましたが、ローカルのk8sクラスターの操作をする際は特に気になりませんでした。検証時には積極的に使っていきたいです。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!