Macのzshでocコマンドのタブ補完

# 概要
ocコマンドのタブ補完のやり方は"linux"の`bash`の場合はOCPのドキュメントのCLIツールの以下の箇所に記載されていますが、Macで`zsh`でやる場合はここには記載されていません。
- [OCP 4.9 Docs / CLI ツール / 2. OpenShift CLI (oc) / 2.2. OpenShift CLI の設定 / 2.2.1. タブ補完の有効化](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.9/html-single/cli_tools#cli-enabling-tab-completion_cli-configuring-cli)

ただ、`oc completion --help`や、上のドキュメントの[2.4.1.15. oc completion](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.9/html-single/cli_tools#_oc-completion)のリファレンスのところに`zsh`の場合のやり方の記載もあったので、今回はMacで`zsh`の場合のocコマンドのタブ補完を設定してみました。

```
Mac:~ % oc completion --help
(略)
  # Load the oc completion code for zsh[1] into the current shell
  source <(oc completion zsh)
  # Set the oc completion code for zsh[1] to autoload on startup
  oc completion zsh > "${fpath[1]}/_oc"
```
ただ、やってみたところ自分の環境が悪いのかなかなかうまくできませんでした。。
ですので、一旦設定がうまくいった際の手順をメモとして残しておきます。
（きっと本当はこんな手順をやる必要はないと思います。。）

**As of 2022/08/31追記**
当記事下部の[追記(2022/08/31)](https://qiita.com/t_sweetfish/items/09e014b9e9e44a1638f7#%E8%BF%BD%E8%A8%98)欄でも記載のように、OCP 4.11.0でFixされ、4.10でのWorkaroundが記載されたKBもあるみたいです。
(一応以下の記事もそのまま残しておきます。)


## (前提) zsh-completionsの導入と設定
zshを使っているのでzshでタブ補完の設定をします。
brewで`zsh-completions`をインストールしておきます。

```
Mac:~ % brew install zsh-completion
(略)
Mac:~ % brew list -1
==> Formulae
aws-iam-authenticator
bash-completion
eks-anywhere
eksctl
kind
zsh-completions
Mac:~ %
```

インストール時表示されるメッセージ、または`brew info zsh-completion`コマンドの出力に従って、`~/.zshrc`を修正し、あとは適宜言われた通りに`~/.zcompdump`を削除したり`/usr/local/share/zsh`の権限を変更します。

```
Mac:~ % brew info zsh-completion
(略)
To activate these completions, add the following to your .zshrc:

  if type brew &>/dev/null; then
    FPATH=$(brew --prefix)/share/zsh-completions:$FPATH

    autoload -Uz compinit
    compinit
  fi

You may also need to force rebuild `zcompdump`:

  rm -f ~/.zcompdump; compinit

Additionally, if you receive "zsh compinit: insecure directories" warnings when attempting
to load these completions, you may need to run this:

  chmod -R go-w '/usr/local/share/zsh'

(略)
Mac:~ %
```

修正後の `~/.zshrc`

```
Mac:~ % cat .zshrc
if type brew &>/dev/null; then
  FPATH=$(brew --prefix)/share/zsh-completions:$FPATH

  autoload -Uz compinit
  compinit
fi

PROMPT='Mac:%c %# '
Mac:~ %
```

# ocコマンドのダウンロード

OCP4.9.0を使用していたので、ocコマンドも4.9.0をダウンロードしました。

- ocコマンドは、以下のサイトからダウンロードできます。
    - [ダウンロード / Red Hat OpenShift Container Platform製品のソフトウェア](https://access.redhat.com/downloads/content/290)
- サブスクリプションがなければ以下のミラーサイトからもダウンロードできます。
    - [ミラーサイト](https://mirror.openshift.com/pub/openshift-v4/clients/ocp/)
- OCPを導入済みの場合は、OCPのコンソールの右上のOCPコンソールの右上のはてなマーク -> コマンドラインツールからもダウンロードできます。

今回はバージョンはミラーサイトからダウンロードしました。
Macなので`openshift-client-mac-4.9.0.tar.gz`をダウンロードします。
該当モジュールのリンクのアドレスをコピーしてcurlコマンドでダウンロードしました。

```
Mac:4.9.0 % curl -s -O https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.9.0/openshift-client-mac-4.9.0.tar.gz
Mac:4.9.0 % curl -s -O https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.9.0/release.txt
Mac:4.9.0 % curl -s -O https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.9.0/sha256sum.txt
Mac:4.9.0 %
Mac:4.9.0 % ls -l
total 82056
-rw-r--r--  1 xxx  staff  41481963 11 23 20:34 openshift-client-mac-4.9.0.tar.gz
-rw-r--r--  1 xxx  staff     24656 11 23 20:35 release.txt
-rw-r--r--  1 xxx  staff       852 11 23 20:35 sha256sum.txt
Mac:4.9.0 %
Mac:4.9.0 % shasum -a 256 openshift-client-mac-4.9.0.tar.gz
7e4b0880c2b46e5b49809a4c5388b439d2c5b5369354ea0be667d2173bc36534  openshift-client-mac-4.9.0.tar.gz
Mac:4.9.0 %
Mac:4.9.0 % grep openshift-client-mac-4.9.0.tar.gz sha256sum.txt
7e4b0880c2b46e5b49809a4c5388b439d2c5b5369354ea0be667d2173bc36534  openshift-client-mac-4.9.0.tar.gz
Mac:4.9.0 %
```

```
Mac:4.9.0 % tar zxf openshift-client-mac-4.9.0.tar.gz
Mac:4.9.0 %
Mac:4.9.0 % ls -l
total 479120
-rw-r--r--  1 xxx  staff       954 10  1 09:41 README.md
-rwxr-xr-x  2 xxx  staff  98469344 10  1 09:41 kubectl
-rwxr-xr-x  2 xxx  staff  98469344 10  1 09:41 oc
-rw-r--r--  1 xxx  staff  41481963 11 23 20:34 openshift-client-mac-4.9.0.tar.gz
-rw-r--r--  1 xxx  staff     24656 11 23 20:35 release.txt
-rw-r--r--  1 xxx  staff       852 11 23 20:35 sha256sum.txt
Mac:4.9.0 %
```

PATHが切れているところにocコマンドのリンクを貼るか移動させます。
複数バージョンのOCPクラスターがある場合はリンクを作成した方ががいいかもしれませんが、`/usr/local/bin`に直接配置しました。

```
Mac:4.9.0 % cp -p oc /usr/local/bin/oc
Mac:4.9.0 %
Mac:4.9.0 % ls -l /usr/local/bin/oc
-rwxr-xr-x  1 xxx  staff  98469344 10  1 09:41 /usr/local/bin/oc
Mac:4.9.0 %
Mac:4.9.0 % oc version
Client Version: 4.9.0
error: You must be logged in to the server (Unauthorized)
Mac:4.9.0 %
```

kubectlは他のクラスタもあるのでバージョンを合わせる必要はなかったのですが、一応上述で取得したバージョンのものに置き直しました。

```
Mac:4.9.0 % cp -p kubectl /usr/local/bin/kubectl
Mac:4.9.0 %
Mac:4.9.0 % kubectl version
Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v0.21.0-beta.1", GitCommit:"96e95cef877ba04872b88e4e2597eabb0174d182", GitTreeState:"clean", BuildDate:"2021-10-01T00:41:12Z", GoVersion:"go1.16.6", Compiler:"gc", Platform:"darwin/amd64"}
error: You must be logged in to the server (the server has asked for the client to provide credentials)
Mac:4.9.0 %
```

# ocコマンドのzshのタブ補完

設定方法は`oc completion`コマンドヘルプに従うことにします。
`source <(oc completion zsh)`をしてもよいですが、自動で読み込まれるようにします。

```
Mac:~ % oc completion --help
(略)
  # Load the oc completion code for zsh[1] into the current shell
  source <(oc completion zsh)
  # Set the oc completion code for zsh[1] to autoload on startup
  oc completion zsh > "${fpath[1]}/_oc"
```


zsh-completionの初期設定で`~/.zshrc`に`FPATH`を設定を追加したので`FPATH`に追加した1つ目の要素のディレクトリに、`oc completion zsh`の出力を`_oc`という名前で保存します。

```
Mac:~ % echo ${fpath[1]}
/usr/local/share/zsh-completions
Mac:~ %
Mac:~ % ls -l ${fpath[1]}/_oc
ls: /usr/local/share/zsh-completions/_oc: No such file or directory
Mac:~ %
Mac:~ % oc completion zsh > "${fpath[1]}/_oc"
Mac:~ %
Mac:~ % ls -l ${fpath[1]}/_oc
-rw-r--r--  1 xxx  admin  5596 11 26 16:02 /usr/local/share/zsh-completions/_oc
Mac:~ %
```

設定を確認するために一旦ターミナルを抜けました。

```
Mac:~ % rm -f ~/.zcompdump
Mac:~ % exit
```

ただ、私の環境では、この手順では、ocコマンドのタブ補完が効きませんでした。。。

```
Mac:~ % oc 
Applications/     Documents/        Library/          Music/            Public/           dev-cluster/      getting-started/
Desktop/          Downloads/        Movies/           Pictures/         demo/             dev-cluster.yaml
```

# `_oc`の中身の確認

`_oc`の中身（`oc completion zsh`の出力）を見てみます。
これを見ると、`compdef`で、`_oc`がコメントアウトされているのが問題かも？？とあたりをつけてみました。

```
Mac:~ % cat /usr/local/share/zsh-completions/_oc | head -n 5
#compdef kubectl
compdef _kubectl kubectl

#compdef _oc oc

Mac:~ %
```

# 最終的にやってみたこと

kubectlとocに関するzshのタブ補完設定を何パターンか試してみました。
結果として以下のパターンで、ocコマンドとkubectlコマンドの両方ともタブ補完が出来るようになりました。。。

- (1) `_oc`の作成と`_kubectl`の削除
    - ocコマンドのタブ補完用の`_oc`ファイルを作成しました。
    - `_oc`と`_kubectl`の両方があるとocコマンドのタブ補完はされなかったため、`_kubectl`の削除しました。
- (2) `_oc`ファイルの修正
    - `_oc`ファイルで`compdef _kubectl kubectl`をコメントアウトし、`compdef _oc oc`を有効化しました。
- (3) 設定の反映
    - タブ補完を有効化するために`~/.zcompdump`を消して再度ターミナルを起動しました。
- (4) 設定の確認
    - なぜかocコマンドではタブ補完はすぐには効きませんでした。
    - 一旦先にkubectlコマンドでタブ補完をすると、ocコマンドでもタブ補完できるようになりました。

ちょっと何を言っているかわからないと思いますので実際にやった設定を記載します。

## (0) zsh-completionの有効化
`~/.zshrc`では、`zsh-completion`の有効化の設定のみにしています。
(`source <(oc completion zsh)`などは追加していません。(私の環境ではこの設定はうまくいかなかった。。))

```
Mac:~ % cat .zshrc
if type brew &>/dev/null; then
  FPATH=$(brew --prefix)/share/zsh-completions:$FPATH

  autoload -Uz compinit
  compinit
fi

#PS1="Mac: \W $ "
PROMPT='Mac:%c %# '
Mac:~ %
```


## (1) `_oc`の作成と`_kubectl`の削除
ocコマンドのタブ補完用の`_oc`ファイルを作成しました。
`_oc`と`_kubectl`の両方があるとocコマンドのタブ補完はされなかったため、`_kubectl`の削除しました。

```
Mac:~ % oc completion --help | grep fpath
  oc completion zsh > "${fpath[1]}/_oc"
Mac:~ %
Mac:~ % oc completion zsh > "${fpath[1]}/_oc"
Mac:~ %
Mac:~ % ls -l ${fpath[1]}/_oc
-rw-r--r--  1 xxx  admin  5596 11 26 15:47 /usr/local/share/zsh-completions/_oc
Mac:~ %
```

```
Mac:~ % ls -l ${fpath[1]}/_kubectl
ls: /usr/local/share/zsh-completions/_kubectl: No such file or directory
Mac:~ %
```
（brewでkubernetes-cliを導入している場合は、`/usr/local/share/zsh/site-functions`の方に`_kubectl`があるかもしれません。）

## (2) `_oc`ファイルの修正
`_oc`ファイルで`compdef _kubectl kubectl`をコメントアウトし、`compdef _oc oc`を有効化しました。

```
Mac:~ % cat $fpath[1]/_oc | head -n 5
#compdef kubectl
compdef _kubectl kubectl

#compdef _oc oc

Mac:~ %
Mac:~ % vi $fpath[1]/_oc
Mac:~ % cat $fpath[1]/_oc | head -n 5
#compdef kubectl
#compdef _kubectl kubectl                         # コメントアウトする

compdef _oc oc                                    # コメントを外す

Mac:~ %
```

## (3) 設定の反映
タブ補完を有効化するために`~/.zcompdump`を消して再度ターミナルを起動しました。

```
Mac:~ % rm -f ~/.zcompdump
Mac:~ % exit
```

## (4) 設定の確認
なぜかocコマンドではタブ補完はすぐには効きませんでした。

```
Mac:~ % oc
Applications/           Downloads/              Music/                  demo/                   getting-started/
Desktop/                Library/                Pictures/               dev-cluster/            kubectl-completion-zsh
Documents/              Movies/                 Public/                 dev-cluster.yaml        oc-completion-zsh
```

一旦先に、kubectlコマンドの方をやってみるとこちらはタブ補完が効いていました。

```
Mac:~ % kubectl
annotate       -- リソースのアノテーションを更新する
api-resources  -- Print the supported API resources on the server
api-versions   -- Print the supported API versions on the server, in the form of "group/version"
apply          -- Apply a configuration to a resource by file name or stdin
attach         -- Attach to a running container
auth           -- Inspect authorization
(略)
Mac:~ % kubectl get pod
poddisruptionbudgets.policy                                      pods.metrics.k8s.io
podmonitors.monitoring.coreos.com                                podsecuritypolicies.policy
podnetworkconnectivitychecks.controlplane.operator.openshift.io  podtemplates
pods
```

kubectlコマンドのタブ補完ができるようになったら、ocコマンドでもタブ補完が効くようになりました。。。

```
Mac:~ % oc
adm              -- Tools for managing a cluster
annotate         -- Update the annotations on a resource
api-resources    -- Print the supported API resources on the server
api-versions     -- Print the supported API versions on the server, in the form of "group/version"
apply            -- Apply a configuration to a resource by file name or stdin
(略)
Mac:~ % oc get pod
poddisruptionbudgets.policy                                      pods.metrics.k8s.io
podmonitors.monitoring.coreos.com                                podsecuritypolicies.policy
podnetworkconnectivitychecks.controlplane.operator.openshift.io  podtemplates
pods
```

やっとzshでocコマンドのタブ補完とkubectlのタブ補完も同時にできるようになりました。
なぜこんな変な手順をしなくてはいけなかったかは、おそらく私のMac環境のせい・・・？


### (補足)
名前空間をタブで補完させるのは、kubectlコマンドは出来たのですが、ocコマンドでは出来ませんでした。。。この差異はなんだろう。。。

```
Mac:~ % kubectl get pod -n kube-
kube-node-lease  kube-public      kube-system
Mac:~ % 
Mac:~ % oc get pod -n
Applications/           Downloads/              Music/                  demo/                   getting-started/
Desktop/                Library/                Pictures/               dev-cluster/            kubectl-completion-zsh
Documents/              Movies/                 Public/                 dev-cluster.yaml        oc-completion-zsh
Mac:~ % 
```

# (追記)

**as of 2022/08/31**

やっぱり2022/01/05でできたというのも勘違い？で、再度M1 MacでOCP 4.10.xで試したらocコマンドのタブ補完はできませんでした。
KBを探してみたら以下のものを見つけました。まさに今回の事象です。
- [KB / ZSH completions do not work with oc client 4.9](https://access.redhat.com/solutions/6896731)

4.10での解決策は今回の記事でやった対応であっていたようで、`oc completion zsh`の出力から`kubectl`の文字列を`oc`に置き換えるというものみたいです。

なお、これは、OCP 4.11では[4.11.0 bug fix and security update](https://access.redhat.com/errata/RHSA-2022:5069)の中で修正されており([BZ - 2024427 - oc completion zsh doesn't auto complete](https://bugzilla.redhat.com/show_bug.cgi?id=2024427))、[known issue](https://github.com/openshift/oc/issues/968)を見ると、OCP4.10にも取り込まれる予定？のようです。



**as of 2022/01/05**

新しく購入したM1 MacBook Airで設定してみたら、上述のようなことは実施せず、`source <(oc completion zsh)`を.zshrcに記載するだけで、ocコマンドのタブ補完は普通にできていました。
(`oc completion zsh > "${fpath[1]}/_oc"`の方はやっぱりできなかった・・。)

前のMacBookはなんだったんだろう。。。と思いますが、上述の内容もメモとして残しておきます。

```
Mac: ~ % cat .zshrc

## zsh-completionsの前提

if type brew &>/dev/null; then
  FPATH=$(brew --prefix)/share/zsh-completions:$FPATH

  autoload -Uz compinit
  compinit
fi

# kubectlタブ補完

source <(kubectl completion zsh)

# ocタブ補完

source <(oc completion zsh)

(略)
```

```
Mac: ~ % source .zshrc
Mac: ~ %
Mac: ~ % oc adm
adm              auth             convert          diff             extract          label            new-project      port-forward     replace          scale            tag
annotate         autoscale        cp               edit             get              login            observe          process          rollback         secrets          version
api-resources    cancel-build     create           ex               idle             logout           options          project          rollout          serviceaccounts  wait
api-versions     cluster-info     debug            exec             image            logs             patch            projects         rsh              set              whoami
apply            completion       delete           explain          import-image     new-app          plugin           proxy            rsync            start-build
attach           config           describe         expose           kustomize        new-build        policy           registry         run              status
```