├── Dockerfile ├── LICENSE ├── README.md ├── fx ├── daemonsets │ └── config ├── default │ └── config ├── deployments ├── libs │ ├── confirm.entrypoint │ ├── confirm.sh │ ├── explain.entrypoint │ ├── explain.sh │ ├── node-shell.entrypoint │ ├── node-shell.sh │ ├── pod_containers.entrypoint │ ├── pod_containers.sh │ ├── sa-token.entrypoint │ ├── sa-token.sh │ ├── scale_obj.entrypoint │ ├── scale_obj.sh │ ├── secret_base64_decode.entrypoint │ ├── secret_base64_decode.sh │ ├── tcp_port_pair.entrypoint │ ├── tcp_port_pair.sh │ ├── trivy_scan_image.entrypoint │ ├── trivy_scan_image.sh │ ├── trivy_scan_manifest.entrypoint │ └── trivy_scan_manifest.sh ├── nodes │ └── config ├── pods │ └── config ├── secrets │ └── config ├── serviceaccounts │ └── config ├── services │ └── config └── statefulsets ├── images ├── dmw.png ├── kexplain.png ├── kexplainpod.png ├── kgetpod.png ├── klogs.png ├── kubecuiexplain.gif ├── tmux_main.png └── tmux_windows.png ├── init.sh ├── kubecui.sh ├── kui_start.sh └── tmux-profiles ├── default.yaml.init ├── dev.yaml.init ├── prod.yaml.init └── stg.yaml.init /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:mantic 2 | 3 | WORKDIR /root 4 | RUN apt update && apt install -y curl git tmux tmuxp unzip vim jq 5 | # 6 | # AWSCLI for EKS clusters 7 | # 8 | RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && unzip awscliv2.zip && /root/aws/install 9 | # 10 | # trivy scanner 11 | # 12 | RUN curl -L0 "https://github.com/aquasecurity/trivy/releases/download/v0.48.3/trivy_0.48.3_Linux-64bit.deb" -o "trivy.deb" && dpkg -i trivy.deb 13 | # 14 | # Install kubent. The tool to check for deprecated or removed APIs 15 | # 16 | ENV TERM=xterm 17 | RUN sh -c "$(curl -sSL https://git.io/install-kubent)" 18 | # 19 | # kubecui dependencies 20 | # 21 | RUN git clone https://github.com/junegunn/fzf.git && yes | fzf/install 22 | RUN git clone https://github.com/pymag09/kubecui.git 23 | # 24 | # Add k alias to .bashrc 25 | # 26 | RUN echo "export KUI_PATH=/root/kubecui" >> /root/.bashrc 27 | RUN echo "export FZF_DEFAULT_OPTS=\"--layout=reverse --border\"" >> /root/.bashrc 28 | RUN echo "source /root/kubecui/kubecui.sh" >> /root/.bashrc 29 | # 30 | # Init tmux profiles 31 | # 32 | RUN mkdir /root/.tmuxp 33 | RUN cp /root/kubecui/tmux-profiles/dev.yaml.init ~/.tmuxp/dev.yaml && sed -i 's//"\/root\/\.kube\/dev\.yml"/g' ~/.tmuxp/dev.yaml 34 | RUN cp /root/kubecui/tmux-profiles/stg.yaml.init ~/.tmuxp/stg.yaml&& sed -i 's//"\/root\/\.kube\/stg\.yml"/g' ~/.tmuxp/stg.yaml 35 | RUN cp /root/kubecui/tmux-profiles/prod.yaml.init ~/.tmuxp/prod.yaml&& sed -i 's//"\/root\/\.kube\/prod\.yml"/g' ~/.tmuxp/prod.yaml 36 | RUN sed -i '/^#tmuxp load dev.*/s/^#//g' /root/kubecui/kui_start.sh 37 | 38 | CMD ["/usr/bin/bash", "/root/kubecui/kui_start.sh"] 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 pymag09 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kubecui 2 | 3 | kubeui makes `kubectl` more user friendly. This is still `kubectl` but enhanced with fzf. 4 | 5 | --- 6 | 7 | ## I believe, anybody who is new to kubernetes, must use `kubectl`. Because `kubectl` is the basics. 8 | 9 | --- 10 | 11 | However, kubectl slows you down - requires heavy keyboard typing. In order to alleviate interaction with kubernetes API and describe the fields associated with each supported API resource directly in the Terminal, `kubectl` was complemented by `fzf`. 12 | 13 | ## Dependencies 14 | 15 | * `fzf` (command-line fuzzy finder) - [https://github.com/junegunn/fzf](https://github.com/junegunn/fzf) 16 | * `yq` (portable command-line YAML processor) 17 | * Optional: `tmux` (terminal multiplexer) 18 | * Optional: `trivy` (security scanner) 19 | * Optional: `tmuxp` (tmux sessions manager) 20 | * Optional: `kubent` (the test for removed or deprecated APIs. You can fine more inforamtion here: https://medium.com/@magelan09/unleashing-unlimited-potential-the-secret-to-kubecuis-unmatched-flexibility-4a41ba7003c1) 21 | 22 | ## Three modes 23 | 24 | ### BASIC 25 | 26 | In the basic mode you use only the `k` alias in your terminal window. You type commands like `k get pod -A`, `k logs` and others, do what you need to do, like search for pods, deployments, view the logs and so on. Every time you need to type a new command. This mode is what kubecui was made for. This mode makes work with `kubectl` a little easier. 27 | 28 | ### NORMAL 29 | 30 | Usually we work with more than one cluster. Every time in order to switch a context we type `k config use-context` command. It is a tedious and error prone process (you might deploy or delete something in the wrong context). In the NORMAL mode, we work with a simple interface which has 3 windows - dev,stg,prod. To switch between windows the `Ctrl+b w` shortcut is used. We still need to type commands, like being in BASIC mode, but we switch the context by switching the windows. `k start` activates the mode. 31 | The mode is avaliable if we install optional `tmux` and `tmuxp` packages The `init.sh` script creates a `.tmuxp` folder and copies the `default.yaml` file there. After that, you have to edit the file( `~/.tmuxp/default.yaml`) and make sure that you use actual values instead of < ...abc... > When everything is ready execute `k start` 32 | 33 | ![k start](https://github.com/pymag09/kubecui/blob/main/images/tmux_main.png) 34 | Pay attention to the red rectangle. These are your clusters. `*` next to cluster points to the active window/cluster.Key combinations you may find helpful: 35 | 36 | * **Ctrl+b 1,2,3,n** OR **Ctrl+b w** - switch between windows/clusters 37 | * ![windows](https://github.com/pymag09/kubecui/blob/main/images/tmux_windows.png) 38 | * **Ctrl+b d** - exit multi-widow session 39 | * **Ctrl+b [** - edit mode. You can move cursor, scroll up/down, select and copy text. 40 | * **Ctrl+r** - if you followed the installation instructions for fzf, most probably you use fzf to browse shell history. If you didn't, you should try, cause it is fun and makes your experience with kubecui more plesant. 41 | 42 | ### DARK_SIDE 43 | 44 | The most efficient and the most interactive mode. Requires minimum typing. Unfortunately this mode goes against the main concept of `kubecui`. You don't type commands, rather switch between windows and sessions. You enter this mode by executing `k start`. After `k start` initializes the environment you will be able to switch between sessions. Each session corresponds to a single context (dev,stage or prod). The shortcut for switching between sessions - `Ctrl+b s`. Each session has 10 windows(for pods, deployments, logs, ingresses, configmaps, secrets, services, PV, PVC and one empty window for any commands). Why are there 10 windows? To make it easier to switch between them. Quick switching - `Ctrl+b number from 0-9`. Or `Ctrl+b w`. 45 | 46 | * ![windows](https://github.com/pymag09/kubecui/blob/main/images/dmw.png) 47 | It pops up interface with windows list, use arrow keys to choose the window. 48 | 49 | ### Docker 50 | 51 | How to build and run kubecui (the darkside mode) using docker. 52 | 53 | 1. **kubectl** must be installed on your laptop. Because **kubecui** must use the same version of it, inside a docker container. 54 | 2. There are lines in the Dockerfile: 55 | 56 | ``` 57 | RUN cp /root/kubecui/tmux-profiles/dev.yaml.init ~/.tmuxp/dev.yaml && sed -i 's//"~\/\.kube\/dev\.yml"/g' ~/.tmuxp/dev.yaml 58 | RUN cp /root/kubecui/tmux-profiles/stg.yaml.init ~/.tmuxp/stg.yaml&& sed -i 's//"~\/\.kube\/stg\.yml"/g' ~/.tmuxp/stg.yaml 59 | RUN cp /root/kubecui/tmux-profiles/prod.yaml.init ~/.tmuxp/prod.yaml&& sed -i 's//"~\/\.kube\/prod\.yml"/g' ~/.tmuxp/prod.yaml 60 | ``` 61 | 62 | They add kubeconfig files path and name (~/.kube/dev.yml, ~/.kube/stg.yml, ~/.kube/prod.yml) to the **kubecui** config file (kubecui will search these particular file names). Later, you will mount kubeconfig directory from your laptop to a docker container `-v /.kube:/root/.kube`, which means your's laptop **/.kube/** directory must contain dev.yml, stg.yml, prod.yml. If you want to use different file names, instead of default ones, you must change them the Dockerfile `sed -i 's//"~\/\.kube\/BLA_BLA_SOME_NAME\.yml"/g'` 63 | 64 | 3. Build the image: `docker build -t kubecui:latest . ` 65 | 4. Run kubecui: `docker run -it --rm --name kubecui -v /kubectl:/usr/local/bin/kubectl -v /.kube:/root/.kube kubecui:latest` 66 | 67 | **IMPORTANT**: For AWS EKS clusters you will additionally need `-v /.aws:/root/.aws` 68 | 69 | ## Installation 70 | 71 | ### Dependencies 72 | 73 | There is no script which leads you through the process of installation. This is done intentionally because usually tools like apt, snap, yum and so on, require root privileges, and we want the process to be transparent, at least at the earlier stage. 74 | 75 | * `fzf` - Follow the installation instructions [https://github.com/junegunn/fzf#installation](https://github.com/junegunn/fzf#installation) 76 | * **Optional**: advanced kubectl command completion - [https://github.com/junegunn/fzf/wiki/examples#kubectl](https://github.com/junegunn/fzf/wiki/examples#kubectl) 77 | * For exmaple: 78 | * k -n Hit [ TAB key ] 79 | * k get Hit [ TAB key ] 80 | * `yq` - `snap install yq` OR `apt install yq` 81 | * Optional: `apt install tmux tmuxp` 82 | 83 | ### Clone the repo 84 | 85 | * git clone [https://github.com/pymag09/kubecui.git](https://github.com/pymag09/kubecui.git) 86 | 87 | ### kubecui 88 | 89 | * `chmod +x kubecui.sh kui_start.sh` 90 | 91 | ### kubecui init 92 | 93 | * `init.sh` 94 | * `source ~/.bashrc` 95 | 96 | ## If for some reason init.sh failed 97 | 98 | ### BASIC mode 99 | 100 | make sure that `~/.bashrc` contains this line: 101 | 102 | * `source //kubecui.sh` 103 | 104 | ### NORMAL mode 105 | 106 | In addition to the line for BASIC mode, make sure that `~/.bashrc` contains this line too: 107 | 108 | * `export KUI_PATH="` 109 | 110 | Also the `~/.tmuxp` directory must exist and contain the `default.yaml` file. Remmember to update the file and replace < ...abc... > with actual values. 111 | Finally, check the `kui_start.sh` file and make sure that `tmuxp load default` line is uncommented and `tmuxp load dev stg prod` remains commented out 112 | 113 | ### DARK-SIDE mode 114 | 115 | All the same as for NORMAL mode but instead of `default.yaml` the directory `~/.tmuxp` must contain three files instead: 116 | 117 | * `dev.yaml` 118 | * `stg.yaml` 119 | * `prod.yaml` 120 | 121 | `kui_start.sh`. `tmuxp load default` is commented out. `tmuxp load dev stg prod` is uncommented 122 | 123 | ## kui_start.sh 124 | 125 | Every time you run `k start` it executes `kui_start.sh`. The script initializes the sessions. For example, if you work with AWS EKS and MFA is a part of the authentication process you can put an `awsume` command in the very beginning of the `kui_start.sh`. 126 | 127 | # SORRY. 128 | 129 | I know that not all of you use bash. I really hope that you know how to do the same for other shells. At this moment I am not able to test `kubecui` for all the most popular shells like zsh. 130 | 131 | ## From fzf README file: 132 | 133 | ### Search syntax 134 | 135 | Unless otherwise specified, fzf starts in "extended-search mode" where you can 136 | type in multiple search terms delimited by spaces. e.g. `^music .mp3$ sbtrkt !fire` 137 | 138 | 139 | | Token | Match type | Description | 140 | | ----------- | ---------------------------- | ------------------------------------- | 141 | | `sbtrkt` | fuzzy-match | Items that match`sbtrkt` | 142 | | `'wild` | exact-match (quoted) | Items that include`wild` | 143 | | `^music` | prefix-exact-match | Items that start with`music` | 144 | | `.mp3$` | suffix-exact-match | Items that end with`.mp3` | 145 | | `!fire` | inverse-exact-match | Items that do not include`fire` | 146 | | `!^music` | inverse-prefix-exact-match | Items that do not start with`music` | 147 | | `!.mp3$` | inverse-suffix-exact-match | Items that do not end with`.mp3` | 148 | 149 | ## Commands 150 | 151 | Most probabaly you are falimiar with or already use `k` alias for `kubectl`. If so, you will be happy to hear, that kubecui is k alias in essence. 152 | 153 | * k get \ 154 | ![k get pod](https://github.com/pymag09/kubecui/blob/main/images/kgetpod.png) 155 | * k logs 156 | ![k logs](https://github.com/pymag09/kubecui/blob/main/images/klogs.png) 157 | * k expain 158 | ![k expain](https://github.com/pymag09/kubecui/blob/main/images/kexplain.png) 159 | * k explain \ 160 | ![k explain pod](https://github.com/pymag09/kubecui/blob/main/images/kubecuiexplain.gif) 161 | ![k explain pod](https://github.com/pymag09/kubecui/blob/main/images/kexplainpod.png) 162 | * k get events --all-namespaces 163 | - Get all events. sort by first and last seen 164 | * k config use-context 165 | - Singale panel. Switch between kubeconfig contexts 166 | * k config set ns 167 | - Singale panel. Set default namespace. 168 | * k start 169 | - starts `cluster per window` session 170 | * k stop 171 | - stop and clear session. Without stop next time you run k start it will suggest you to return to previous session 172 | 173 | ## Additional materials 174 | * https://medium.com/@magelan09/unleashing-unlimited-potential-the-secret-to-kubecuis-unmatched-flexibility-4a41ba7003c1 175 | * https://medium.com/@magelan09/kubectl-on-steroids-there-is-life-beyond-k9s-5c214e878c83 176 | * https://medium.com/@magelan09/kubecui-enhanced-interactive-kubectl-dark-side-mode-720a1f19b0bf 177 | * https://medium.com/@magelan09/navigating-kubernetes-effortlessly-with-kubecui-new-shortcuts-and-features-part-3-df3ab0449518 178 | * https://medium.com/@magelan09/kubecui-ephemeral-containers-and-more-part-4-f069d7ebc405 179 | * https://medium.com/@magelan09/kubecui-has-reached-its-first-big-milestone-part-5-in-the-series-of-the-articles-c520c3c33ab1 180 | -------------------------------------------------------------------------------- /fx/daemonsets/config: -------------------------------------------------------------------------------- 1 | HEADER='========================================================================================================== 2 | [F1]Explain [F2]Restart [F3]YAML [F4]Edit [F5]Descr search [F6]Trivy YAML scan [F7]Trivy image scan [F8]Delete [F9]Scale [Ctrl+6]Clone Obj 3 | Scrolling (SHIFT - up/down) || CTRL-/ (change view) || CTRL-R (refresh. omit -o wide) || Ctrl-L (-o wide) 4 | ==========================================================================================================' 5 | 6 | PARAMS+=(--bind "f2:execute:confirm "restart" ${RS_TYPE}/{2} && kubectl --namespace {1} rollout restart ${RS_TYPE} {2}") 7 | PARAMS+=(--bind "f6:execute:trivy_scan_manifest {1} {2} ${RS_TYPE}") 8 | PARAMS+=(--bind "f7:execute:trivy_scan_image {1} {2} ${RS_TYPE}") 9 | PARAMS+=(--bind "f9:execute:confirm "scale" ${RS_TYPE}/{2} && scale_obj ${RS_TYPE} {1} {2}") 10 | -------------------------------------------------------------------------------- /fx/default/config: -------------------------------------------------------------------------------- 1 | PARAMS=() 2 | 3 | HEADER='========================================================================================================== 4 | [F1]Explain [F3]YAML [F4]Edit [F5]Descr search [F8]Delete [Ctrl+6]Clone Obj 5 | Scrolling (SHIFT - up/down) || CTRL-/ (change view) || CTRL-R (refresh. omit -o wide) || Ctrl-L (-o wide) 6 | ==========================================================================================================' 7 | 8 | PARAMS+=(--bind "f1:execute:explain_obj ${RS_TYPE}") 9 | PARAMS+=(--bind "f3:execute:kubectl get $RS_TYPE ${SCOPED:+"{2} -n {1}"}${NONSCOPED:-"{1}"} -o yaml | less") 10 | PARAMS+=(--bind "f4:execute:kubectl edit $RS_TYPE ${SCOPED:+"{2} -n {1}"}${NONSCOPED:-"{1}"}") 11 | PARAMS+=(--bind "ctrl-6:execute:kubectl get $RS_TYPE ${SCOPED:+"{2} -n {1}"}${NONSCOPED:-"{1}"} -o yaml | yq '.metadata.name = \"{2}-$(openssl rand -hex 5)\"' | kubectl apply -f -") 12 | PARAMS+=(--bind "f5:execute:kubectl describe $RS_TYPE ${SCOPED:+"{2} -n {1}"}${NONSCOPED:-"{1}"} | less") 13 | PARAMS+=(--bind "f8:execute:confirm "delete" $RS_TYPE/{2} && kubectl delete $RS_TYPE ${SCOPED:+"{2} -n {1}"}${NONSCOPED:-"{1}"}") 14 | -------------------------------------------------------------------------------- /fx/deployments: -------------------------------------------------------------------------------- 1 | daemonsets -------------------------------------------------------------------------------- /fx/libs/confirm.entrypoint: -------------------------------------------------------------------------------- 1 | confirm 2 | -------------------------------------------------------------------------------- /fx/libs/confirm.sh: -------------------------------------------------------------------------------- 1 | # 2 | # confirm(action,resource) 3 | # 4 | confirm() 5 | { 6 | [[ "$(echo -e "No\nYes ${1} the ${2}" | fzf --border=double --border-label="╢ Confirmation ╟" --margin 25% --prompt 'Are you sure? ')" == Yes* ]] 7 | } 8 | -------------------------------------------------------------------------------- /fx/libs/explain.entrypoint: -------------------------------------------------------------------------------- 1 | explain_obj 2 | -------------------------------------------------------------------------------- /fx/libs/explain.sh: -------------------------------------------------------------------------------- 1 | __prepare_explain__(){ 2 | export RS_TYPE=$1 3 | 4 | EXPLAIN=$(kubectl explain ${RS_TYPE} --recursive | sed -r 's/FIELDS:/---/' | sed -n '\|---|,$p' | sed -r 's/(\w+)(\t|\s)*.*/\1: /g' | yq -o props -P . | sed -r 's/ =//g') 5 | 6 | for line in $EXPLAIN; do 7 | echo $line 8 | ST=$line 9 | for level in $(echo $line | sed -r 's/^([a-zA-Z\.]+)\.(\w+)$/\1/' | sed -r 's/\./ /g'); do 10 | ST=$(echo $ST | sed -r 's/^([a-zA-Z\.]+)\.(\w+)$/\1/') 11 | echo $ST 12 | done 13 | done | sort | uniq 14 | } 15 | 16 | export -f __prepare_explain__ 17 | 18 | explain_obj(){ 19 | export RS_TYPE=$1 20 | __prepare_explain__ $1 | fzf --layout=reverse --header-lines=1 --info=inline \ 21 | --prompt "CL: $(kubectl config current-context | sed 's/-context$//') NS: $(kubectl config get-contexts | grep "*" | awk '{print $5}')> " \ 22 | --header $'>> Scrolling: SHIFT - up/down || CTRL-/ (change view) Ctrl-f (search word) <<\n\n' \ 23 | --preview-window=right:70% \ 24 | --bind 'ctrl-/:change-preview-window(40%|50%|70%)' \ 25 | --bind 'enter:accept' \ 26 | --bind 'ctrl-f:execute:kubectl explain ${RS_TYPE}.{1} | less' \ 27 | --preview 'kubectl explain ${RS_TYPE}.{1}' 28 | } 29 | -------------------------------------------------------------------------------- /fx/libs/node-shell.entrypoint: -------------------------------------------------------------------------------- 1 | node-shell 2 | -------------------------------------------------------------------------------- /fx/libs/node-shell.sh: -------------------------------------------------------------------------------- 1 | node-shell(){ 2 | shell_pod_json="{\"apiVersion\":\"v1\",\"spec\":{\"volumes\":[{\"name\":\"kube-api-access-g5t5g\",\"projected\":{\"sources\":[{\"serviceAccountToken\":{\"expirationSeconds\":3607,\"path\":\"token\"}},{\"configMap\":{\"name\":\"kube-root-ca.crt\",\"items\":[{\"key\":\"ca.crt\",\"path\":\"ca.crt\"}]}},{\"downwardAPI\":{\"items\":[{\"path\":\"namespace\",\"fieldRef\":{\"apiVersion\":\"v1\",\"fieldPath\":\"metadata.namespace\"}}]}}],\"defaultMode\":420}}],\"containers\":[{\"name\":\"shell\",\"image\":\"docker.io/alpine:3.13\",\"command\":[\"nsenter\"],\"args\":[\"-t\",\"1\",\"-m\",\"-u\",\"-i\",\"-n\",\"sleep\",\"14000\"],\"volumeMounts\":[{\"name\":\"kube-api-access-g5t5g\",\"readOnly\":true,\"mountPath\":\"/var/run/secrets/kubernetes.io/serviceaccount\"}],\"terminationMessagePath\":\"/dev/termination-log\",\"terminationMessagePolicy\":\"File\",\"imagePullPolicy\":\"IfNotPresent\",\"securityContext\":{\"privileged\":true}}],\"restartPolicy\":\"Never\",\"terminationGracePeriodSeconds\":0,\"nodeName\":\"NODE_NAME\",\"hostNetwork\":true,\"hostPID\":true,\"hostIPC\":true,\"tolerations\":[{\"operator\":\"Exists\"}],\"priorityClassName\":\"system-node-critical\",\"priority\":2000001000,\"enableServiceLinks\":true,\"preemptionPolicy\":\"PreemptLowerPriority\"}}" 3 | pod_name_suffix=$(echo $RANDOM | md5sum | head -c 20) 4 | echo -e "\n\nWait until pod will be scheduled. \nIt might take several seconds.\n\n..." 5 | kubectl -n kube-system run \ 6 | kube-shell-${pod_name_suffix} \ 7 | --image=alpine:3.13 \ 8 | --overrides=$(echo $shell_pod_json | sed -e "s/NODE_NAME/${1}/") && \ 9 | sleep 5 && \ 10 | kubectl -n kube-system exec -it kube-shell-${pod_name_suffix} -- bash 11 | } 12 | -------------------------------------------------------------------------------- /fx/libs/pod_containers.entrypoint: -------------------------------------------------------------------------------- 1 | pod_containers 2 | -------------------------------------------------------------------------------- /fx/libs/pod_containers.sh: -------------------------------------------------------------------------------- 1 | pod_containers() 2 | { 3 | kubectl -n ${1} get pod ${2} -o jsonpath='{.spec.containers[*].name}' | tr " " "\n" | fzf --border=double --border-label="╢ Container ╟" --margin 40% 4 | } 5 | -------------------------------------------------------------------------------- /fx/libs/sa-token.entrypoint: -------------------------------------------------------------------------------- 1 | create_sa_token 2 | -------------------------------------------------------------------------------- /fx/libs/sa-token.sh: -------------------------------------------------------------------------------- 1 | create_sa_token() 2 | { 3 | kubectl create secret docker-registry ${2} -n ${1} --from-file /dev/null --dry-run=client -o yaml | \ 4 | sed -r 's/^type:.*$/type\: kubernetes\.io\/service-account-token/' | \ 5 | sed -r "s/creationTimestamp.*/annotations:\n kubernetes.io\/service-account.name: ${2}/" | \ 6 | sed 's/"null": ""//' | \ 7 | kubectl apply -f - 8 | } 9 | -------------------------------------------------------------------------------- /fx/libs/scale_obj.entrypoint: -------------------------------------------------------------------------------- 1 | scale_obj 2 | -------------------------------------------------------------------------------- /fx/libs/scale_obj.sh: -------------------------------------------------------------------------------- 1 | scale_obj () 2 | { 3 | kubectl --namespace ${2} scale ${1} ${3} --replicas=$(seq 0 100 | fzf) 4 | } 5 | -------------------------------------------------------------------------------- /fx/libs/secret_base64_decode.entrypoint: -------------------------------------------------------------------------------- 1 | secret_base64_decode 2 | -------------------------------------------------------------------------------- /fx/libs/secret_base64_decode.sh: -------------------------------------------------------------------------------- 1 | secret_base64_decode() 2 | { 3 | echo '' | fzf --border=double --preview-window=top,99%,wrap --border-label="╢ Base64 decoded ╟" --preview="kubectl get secret ${1} --namespace ${2} -o jsonpath='{.data}' | jq 'walk(if type == \"string\" then @base64d else . end)'" 4 | } 5 | -------------------------------------------------------------------------------- /fx/libs/tcp_port_pair.entrypoint: -------------------------------------------------------------------------------- 1 | tcp_port_pair 2 | -------------------------------------------------------------------------------- /fx/libs/tcp_port_pair.sh: -------------------------------------------------------------------------------- 1 | tcp_port_pair() 2 | { 3 | FZF_DEFAULT_OPTS_ORIG=$FZF_DEFAULT_OPTS 4 | export FZF_DEFAULT_OPTS="--layout=reverse --border=double --border-label=\"╢ Port ╟\" --margin 40%" 5 | 6 | port_number="" 7 | echo "Press Ctrl+C to close the session." 8 | read lower_port upper_port < /proc/sys/net/ipv4/ip_local_port_range 9 | if [[ "${3}" == "service" ]]; then 10 | port_number=$(kubectl -n ${1} get service ${2} -o jsonpath='{.spec.ports[?(@.protocol=="TCP")].port}' | tr " " "\n" | fzf) 11 | fi 12 | if [[ "${3}" == "pod" ]]; then 13 | port_number=$(kubectl -n ${1} get pod ${2} -o jsonpath='{.spec.containers[*].ports[?(@.protocol=="TCP")].containerPort}' | tr " " "\n" | fzf) 14 | fi 15 | while :; do 16 | for (( port = lower_port ; port <= upper_port ; port++ )); do 17 | kubectl -n ${1} port-forward ${3}/${2} $port:$port_number && break 2 18 | done 19 | done 20 | export FZF_DEFAULT_OPTS=$FZF_DEFAULT_OPTS_ORIG 21 | } 22 | -------------------------------------------------------------------------------- /fx/libs/trivy_scan_image.entrypoint: -------------------------------------------------------------------------------- 1 | trivy_scan_image 2 | -------------------------------------------------------------------------------- /fx/libs/trivy_scan_image.sh: -------------------------------------------------------------------------------- 1 | trivy_scan_image() 2 | { 3 | which trivy 4 | if [[ $? == "0" ]]; then 5 | image=$(kubectl -n ${1} get ${3} ${2} --no-headers -o custom-columns='IMAGE:.spec.template.spec.containers[].image' | tr " " "\n" | fzf --border=double --border-label="╢ Image ╟" --margin 40%) 6 | echo ${image} 7 | trivy image -d --severity=CRITICAL,HIGH,MEDIUM ${image} | less 8 | fi 9 | } 10 | -------------------------------------------------------------------------------- /fx/libs/trivy_scan_manifest.entrypoint: -------------------------------------------------------------------------------- 1 | trivy_scan_manifest 2 | -------------------------------------------------------------------------------- /fx/libs/trivy_scan_manifest.sh: -------------------------------------------------------------------------------- 1 | trivy_scan_manifest() 2 | { 3 | which trivy 4 | if [[ $? == "0" ]]; then 5 | tmpfile=$(mktemp -u).yaml 6 | kubectl -n ${1} get ${3}.apps ${2} -o yaml > ${tmpfile} 7 | trivy config -d --severity=CRITICAL,HIGH,MEDIUM ${tmpfile} | less 8 | fi 9 | } 10 | -------------------------------------------------------------------------------- /fx/nodes/config: -------------------------------------------------------------------------------- 1 | HEADER='========================================================================================================== 2 | [F1]Explain [F2]Shell [F3]YAML [F5]Descr search [F6]Cordon [F7]Uncordon [F8]Delete [F9]Drain [F10] Api deprecation report 3 | Scrolling (SHIFT - up/down) || CTRL-/ (change view) || CTRL-R (refresh. omit -o wide) || Ctrl-L (-o wide) 4 | ==========================================================================================================' 5 | 6 | PARAMS+=(--bind 'f2:execute:node-shell {1}') 7 | PARAMS+=(--bind 'f6:execute:confirm "cordon" {1} && kubectl cordon {1}') 8 | PARAMS+=(--bind 'f7:execute:kubectl uncordon {1}') 9 | PARAMS+=(--bind 'f9:execute:confirm "drain" {1} && kubectl drain {1} --ignore-daemonsets --delete-emptydir-data') 10 | PARAMS+=(--bind 'f10:execute:kubent -t $(kubectl version -o yaml | yq .serverVersion.major).$(($(kubectl version -o yaml | yq .serverVersion.minor | sed -E "s/^([0-9]+).*/\1/") + 1)).0 | less -R --use-color') 11 | -------------------------------------------------------------------------------- /fx/pods/config: -------------------------------------------------------------------------------- 1 | HEADER='========================================================================================================== 2 | [F1]Explain [F2]Shell [F3]YAML [F4]Edit [F5]Descr Search [F6]Port forward [F7] DebugContainer [F8]Delete [Ctrl+6]Clone Obj 3 | Scrolling (SHIFT - up/down) || CTRL-/ (change view) || CTRL-R (refresh. omit -o wide) || Ctrl-L (-o wide) 4 | ==========================================================================================================' 5 | 6 | PARAMS+=(--bind 'f2:execute:kubectl exec -it --namespace {1} {2} -c $(pod_containers {1} {2}) -- bash || sh > /dev/tty') 7 | PARAMS+=(--bind 'f6:execute:tcp_port_pair {1} {2} pod') 8 | PARAMS+=(--bind 'f7:execute:kubectl debug {2} --namespace {1} -it --image=ubuntu --share-processes --copy-to {2}-debug-container -- bash') 9 | -------------------------------------------------------------------------------- /fx/secrets/config: -------------------------------------------------------------------------------- 1 | HEADER='========================================================================================================== 2 | [F1]Explain [F3]YAML [F4]Edit [F5]Descr search [F6]Decode [F8]Delete [Ctrl+6]Clone Obj 3 | Scrolling (SHIFT - up/down) || CTRL-/ (change view) || CTRL-R (refresh. omit -o wide) || Ctrl-L (-o wide) 4 | ==========================================================================================================' 5 | 6 | PARAMS+=(--bind "f6:execute:secret_base64_decode {2} {1}") 7 | -------------------------------------------------------------------------------- /fx/serviceaccounts/config: -------------------------------------------------------------------------------- 1 | HEADER='========================================================================================================== 2 | [F1]Explain [F3]YAML [F4]Edit [F5]Descr search [F6]SA Token [F8]Delete [Ctrl+6]Clone Obj 3 | Scrolling (SHIFT - up/down) || CTRL-/ (change view) || CTRL-R (refresh. omit -o wide) || Ctrl-L (-o wide) 4 | ==========================================================================================================' 5 | 6 | PARAMS+=(--bind "f6:execute:create_sa_token {1} {2}") 7 | -------------------------------------------------------------------------------- /fx/services/config: -------------------------------------------------------------------------------- 1 | HEADER='========================================================================================================== 2 | [F1]Explain [F2]Shell [F3]YAML [F4]Edit [F5]Descr Search [F6]Port forward [F7] DebugContainer [F8]Delete [Ctrl+6]Clone Obj 3 | Scrolling (SHIFT - up/down) || CTRL-/ (change view) || CTRL-R (refresh. omit -o wide) || Ctrl-L (-o wide) 4 | ==========================================================================================================' 5 | 6 | PARAMS+=(--bind 'f6:execute:tcp_port_pair {1} {2} service') 7 | -------------------------------------------------------------------------------- /fx/statefulsets: -------------------------------------------------------------------------------- 1 | daemonsets -------------------------------------------------------------------------------- /images/dmw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pymag09/kubecui/8fe8802cdcb5511cf2756ab3df50634de4a33716/images/dmw.png -------------------------------------------------------------------------------- /images/kexplain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pymag09/kubecui/8fe8802cdcb5511cf2756ab3df50634de4a33716/images/kexplain.png -------------------------------------------------------------------------------- /images/kexplainpod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pymag09/kubecui/8fe8802cdcb5511cf2756ab3df50634de4a33716/images/kexplainpod.png -------------------------------------------------------------------------------- /images/kgetpod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pymag09/kubecui/8fe8802cdcb5511cf2756ab3df50634de4a33716/images/kgetpod.png -------------------------------------------------------------------------------- /images/klogs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pymag09/kubecui/8fe8802cdcb5511cf2756ab3df50634de4a33716/images/klogs.png -------------------------------------------------------------------------------- /images/kubecuiexplain.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pymag09/kubecui/8fe8802cdcb5511cf2756ab3df50634de4a33716/images/kubecuiexplain.gif -------------------------------------------------------------------------------- /images/tmux_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pymag09/kubecui/8fe8802cdcb5511cf2756ab3df50634de4a33716/images/tmux_main.png -------------------------------------------------------------------------------- /images/tmux_windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pymag09/kubecui/8fe8802cdcb5511cf2756ab3df50634de4a33716/images/tmux_windows.png -------------------------------------------------------------------------------- /init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function copy_dm_profile() 4 | { 5 | if [[ ! -f ~/.tmuxp/$1 ]]; then 6 | cp ./tmux-profiles/$1.init ~/.tmuxp/$1 7 | return 0 8 | else 9 | echo "~/.tmuxp/$1.yaml already exists" 10 | return 1 11 | fi 12 | } 13 | 14 | if [[ -z $(grep "source ${response:-$(pwd)}/kubecui.sh" ~/.bashrc) ]]; then 15 | read -r -p "Add kubecui to .bashrc. [source $(pwd)/kubecui.sh] " response 16 | # 17 | # kubecui.sh creates 'k' alias. Adding it to the .bashrc file to make it work. 18 | # 19 | echo "source ${response:-$(pwd)}/kubecui.sh" >> ~/.bashrc 20 | fi 21 | read -r -p "Will you use tmux and tmuxp? [y/n] " response 22 | if [[ $response =~ ^([yY])$ ]]; then 23 | mkdir -p ~/.tmuxp 24 | read -r -p "Do you want to initialize DARK-SIDE mode? [y/n] " darkside 25 | if [[ "$darkside" =~ ^([nN])$ ]]; then 26 | # 27 | # NORMAL mode creates one tmux session with 3 windows. Each window corresponds to the environment (dev,stage,prod). 28 | # Settings for the NORMAL mode are stored in the tmux profile file - default.yaml 29 | # All tmux profiles are stored in the $HOME/.tmuxp directory 30 | # If your answer NO, only file default.yaml will be copied to the .tmuxp directory 31 | # 32 | copy_dm_profile default.yaml 33 | else 34 | # 35 | # DARK-SIDE mode creates 3 tmux sessions for each environment (dev,stage,prod). 36 | # Settings for the DARK-SIDE mode are stored in the tmux profile, one profile per environament. 37 | # All tmux profiles are stored in the $HOME/.tmuxp directory 38 | # If your answer YES, three files(dev.yaml, stg.yaml, prod.yaml) will bw copied to the .tmuxp directory 39 | # 40 | # DEV 41 | # 42 | copy_dm_profile dev.yaml 43 | if [[ $? -eq 0 ]]; then 44 | read -r -p "kubeconfig for dev environment [~/.kube/dev.yml] " kubecfg 45 | kubecfg=$(echo $kubecfg | sed 's/\//\\\//g') 46 | sed -i 's//'"${kubecfg:-~\/.kube\/dev.yml}"'/g' ~/.tmuxp/dev.yaml 47 | fi 48 | # 49 | # STG 50 | # 51 | copy_dm_profile stg.yaml 52 | if [[ $? -eq 0 ]]; then 53 | read -r -p "kubeconfig for stg environment [~/.kube/stg.yml] " kubecfg 54 | kubecfg=$(echo $kubecfg | sed 's/\//\\\//g') 55 | sed -i 's//'"${kubecfg:-~\/.kube\/stg.yml}"'/g' ~/.tmuxp/stg.yaml 56 | fi 57 | # 58 | # prod 59 | # 60 | copy_dm_profile prod.yaml 61 | if [[ $? -eq 0 ]]; then 62 | read -r -p "kubeconfig for prod environment [~/.kube/prod.yml] " kubecfg 63 | kubecfg=$(echo $kubecfg | sed 's/\//\\\//g') 64 | sed -i 's//'"${kubecfg:-~\/.kube\/prod.yml}"'/g' ~/.tmuxp/prod.yaml 65 | fi 66 | fi 67 | if [[ -z $(grep "export KUI_PATH=" ~/.bashrc) ]]; then 68 | if [[ -z $(grep -E 'export KUI_PATH=.*' ~/.bashrc) ]]; then 69 | read -r -p "Add \"KUI_PATH\" to .bashrc? [$(pwd)] " response 70 | # 71 | # kui_start.sh activates multi-window, multi-session mode. Regardless of what mode you have chosen, either NORMAL or DARK-SIDE 72 | # you can start it by typeing 'k start' command. 73 | # 74 | echo "export KUI_PATH=${response:-$(pwd)}" >> ~/.bashrc 75 | if [[ "$darkside" =~ ^([nN])$ ]]; then 76 | sed -i 's/#tmuxp load default/tmuxp load default/g' ${response:-$(pwd)}/kui_start.sh 77 | else 78 | sed -i 's/#tmuxp load dev stg prod/tmuxp load dev stg prod/g' ${response:-$(pwd)}/kui_start.sh 79 | fi 80 | fi 81 | fi 82 | fi 83 | cat < " \ 22 | --header $'>> CTRL-L (open log in editor) || CTRL-R (refresh) || CTRL-/ (change view) <<\n\n' \ 23 | --color ${ENV_FZF_COLOR} \ 24 | --bind 'ctrl-/:change-preview-window(50%|80%)' \ 25 | --bind 'ctrl-l:execute:${EDITOR:-vim} <(kubectl logs --all-containers --namespace {1} {2}) > /dev/tty' \ 26 | --bind 'ctrl-r:reload:$FZF_DEFAULT_COMMAND' \ 27 | --preview-window up:follow,80%,wrap \ 28 | --preview 'kubectl logs --follow --all-containers --tail=200 --namespace {1} {2}' "$@" 29 | } 30 | 31 | __explain__(){ 32 | export FZF_DEFAULT_COMMAND="kubectl api-resources" 33 | fzf --layout=reverse --header-lines=1 --info=inline \ 34 | --prompt "CL: $(kubectl config current-context | sed 's/-context$//') NS: $(kubectl config get-contexts | grep "*" | awk '{print $5}')> " \ 35 | --header $'>> Scrolling: SHIFT - up/down || CTRL-/ (change view) || CTRL-R (refresh. omit -o wide) || Ctrl-L (-o wide) || Ctrl-f (search word) <<\n\n' \ 36 | --preview-window=right:50% \ 37 | --color ${ENV_FZF_COLOR} \ 38 | --bind 'ctrl-/:change-preview-window(70%|40%|50%)' \ 39 | --bind 'enter:accept' \ 40 | --bind 'ctrl-r:reload:$FZF_DEFAULT_COMMAND' \ 41 | --bind 'ctrl-L:reload:$FZF_DEFAULT_COMMAND_WIDE' \ 42 | --bind 'ctrl-f:execute:kubectl describe $RS_TYPE {2} -n {1} | less' \ 43 | --preview 'kubectl explain {1}' 44 | } 45 | 46 | __get_obj__(){ 47 | RS_TYPE=$(echo $1 | base64 -d) 48 | export FZF_DEFAULT_COMMAND_WIDE="${FZF_DEFAULT_COMMAND} -o wide" 49 | source "$KUI_PATH"/fx/default/config 50 | if [[ -f "$KUI_PATH"/fx/"${RS_TYPE}"/config ]]; then 51 | source "$KUI_PATH"/fx/"${RS_TYPE}"/config 52 | fi 53 | 54 | fzf --layout=reverse -m --header-lines=1 --info=inline \ 55 | --prompt "[ $RS_TYPE ] CL: $(kubectl config current-context | sed 's/-context$//') NS: $(kubectl config get-contexts | grep "*" | awk '{print $5}')> " \ 56 | --header $"${HEADER}" \ 57 | --color ${ENV_FZF_COLOR} \ 58 | --preview-window=right:50% \ 59 | --bind 'ctrl-/:change-preview-window(99%|70%|40%|0|50%)' \ 60 | --bind 'ctrl-r:reload:$FZF_DEFAULT_COMMAND' \ 61 | --bind 'ctrl-L:reload:$FZF_DEFAULT_COMMAND_WIDE' \ 62 | "${PARAMS[@]}" \ 63 | --bind 'enter:accept' \ 64 | --preview "kubectl describe $RS_TYPE {1}" 65 | } 66 | 67 | __get_obj_all__(){ 68 | RS_TYPE=$(echo $1 | base64 -d) 69 | export FZF_DEFAULT_COMMAND_WIDE="${FZF_DEFAULT_COMMAND} -o wide" 70 | source "$KUI_PATH"/fx/default/config 71 | if [[ -f "$KUI_PATH"/fx/"${RS_TYPE}"/config ]]; then 72 | source "$KUI_PATH"/fx/"${RS_TYPE}"/config 73 | fi 74 | 75 | fzf --layout=reverse -m --header-lines=1 --info=inline \ 76 | --prompt "[ $RS_TYPE ] CL: $(kubectl config current-context | sed 's/-context$//') NS: $(kubectl config get-contexts | grep "*" | awk '{print $5}') >" \ 77 | --header $"${HEADER}" \ 78 | --color ${ENV_FZF_COLOR} \ 79 | --preview-window 'right,50%' \ 80 | --bind 'ctrl-/:change-preview-window(99%|70%|40%|0|50%)' \ 81 | --bind 'enter:accept' \ 82 | --bind 'ctrl-r:reload:$FZF_DEFAULT_COMMAND' \ 83 | --bind 'ctrl-L:reload:$FZF_DEFAULT_COMMAND_WIDE' \ 84 | "${PARAMS[@]}" \ 85 | --preview "kubectl describe $RS_TYPE {2} -n {1}" 86 | } 87 | 88 | __top_all__(){ 89 | export FZF_DEFAULT_COMMAND="kubectl top pod -A --no-headers" 90 | fzf --info=inline --layout=reverse \ 91 | --prompt "CL: $(kubectl config current-context | sed 's/-context$//') NS: $(kubectl config get-contexts | grep "*" | awk '{print $5}')> " \ 92 | --header $'>> Sort by .. Ctrl + u: CPU || Ctrl + m: MEM <<\n\n' \ 93 | --preview-window=right:50% \ 94 | --bind 'ctrl-/:change-preview-window(70%|40%|50%)' \ 95 | --bind 'enter:accept' \ 96 | --bind 'ctrl-u:reload:$FZF_DEFAULT_COMMAND | sort -k 3 -h -r' \ 97 | --bind 'ctrl-m:reload:$FZF_DEFAULT_COMMAND | sort -k 4 -h -r' \ 98 | --preview 'kubectl describe pod {2} -n {1}' 99 | } 100 | 101 | __get_events_all__(){ 102 | export FZF_DEFAULT_COMMAND="kubectl get event --all-namespaces" 103 | fzf --info=inline --header-lines=1 --layout=reverse \ 104 | --prompt "CL: $(kubectl config current-context | sed 's/-context$//') NS: $(kubectl config get-contexts | grep "*" | awk '{print $5}')> " \ 105 | --header $'>> Ctrl+r: Reload || Sort by .. Ctrl + k: first time || Ctrl + l: last time <<\n\n' \ 106 | --color ${ENV_FZF_COLOR} \ 107 | --bind 'enter:accept' \ 108 | --bind 'ctrl-r:reload:$FZF_DEFAULT_COMMAND' \ 109 | --bind 'ctrl-l:reload:$FZF_DEFAULT_COMMAND --sort-by=".lastTimestamp"' \ 110 | --bind 'ctrl-k:reload:$FZF_DEFAULT_COMMAND --sort-by=".firstTimestamp"' 111 | } 112 | 113 | __normalize_resource_data() { 114 | local word="$1" 115 | 116 | if [[ $word =~ \. ]]; then 117 | echo "$word" 118 | return 0 119 | fi 120 | while read -r plural short _; do 121 | if [ "$word" == "$plural" ] || [ "$word" == "$short" ] || [ "$word" == "$(echo "$plural" | sed -r 's/s$//')" ] || [ "$word" == "$(echo "$plural" | sed -r 's/e?s$//')" ]; then 122 | echo "$plural" 123 | break 124 | fi 125 | done < <(kubectl api-resources --no-headers | awk '{print $1, $2}' | awk '{if (NF == 1) $2 = $1; print}' | sort -r) 126 | } 127 | 128 | k() { 129 | OBJ=$(__normalize_resource_data $(echo "$@" | sed -E 's/^.*get[[:space:]]([[:alnum:]]+[[:space:]]?[[:lower:]]+[-0-9.[:lower:]]*)[[:space:]]?(-)?.*$/\1/')) 130 | export SCOPED=$(kubectl api-resources --no-headers --namespaced | grep -E "^$(echo $OBJ | sed -r "s/^([a-zA-Z]+).*/\1/")" | wc -l | tr -d " "| tr -d '0' | sed -r 's/[0-9]+/ /') 131 | export NONSCOPED=$SCOPED 132 | 133 | local input="$@" 134 | 135 | params=() 136 | options=() 137 | 138 | local args=($input) 139 | 140 | local skip_next=false 141 | for i in "${!args[@]}"; do 142 | if [[ "$skip_next" == "true" ]]; then 143 | skip_next=false 144 | continue 145 | fi 146 | 147 | local arg="${args[$i]}" 148 | 149 | if [[ "$arg" == --*=* ]]; then 150 | options+=("$arg") 151 | elif [[ "$arg" == -* && "${args[$i+1]}" != -* && "${args[$i+1]}" != "" ]]; then 152 | options+=("$arg ${args[$i+1]}") 153 | skip_next=true 154 | elif [[ "$arg" == -* ]]; then 155 | options+=("$arg") 156 | else 157 | params+=("$arg") 158 | fi 159 | done 160 | 161 | case "${params[0]}" in 162 | "config" ) 163 | if [[ "${params[@]}" == "config use-context" ]]; then 164 | kubectl config use-context $(kubectl config get-contexts | fzf --layout=reverse --header-lines=1 | sed -r 's/^\*?\s*([-0-9a-zA-Z]*).*/\1/') 165 | fi 166 | if [[ ${params[@]} == "config set ns" ]]; then 167 | CURRENT_CONTEXT=$(kubectl config current-context) 168 | kubectl config set contexts.${CURRENT_CONTEXT}.namespace $(kubectl get ns | fzf --layout=reverse --header-lines=1 | sed -r 's/^\*?\s*([-0-9a-zA-Z]*).*/\1/') 169 | fi 170 | ;; 171 | "logs") __logs__;; 172 | "stop") tmux kill-session -a 173 | tmux kill-session;; 174 | "start") if [[ -n $(which tmuxp) ]]; then 175 | ${KUI_PATH}/kui_start.sh 176 | else 177 | echo "Can not find tmux/tmuxp. Please follow the instructions in the README file to install these tools" 178 | fi;; 179 | 180 | "explain" ) 181 | if [[ "$params[1]" == "" ]]; then 182 | __explain__ 183 | else 184 | explain_obj $(echo "$@" | sed -r 's/^.*explain[[:space:]]([[:lower:]]+)$/\1/') 185 | fi 186 | ;; 187 | 188 | "top" ) 189 | what=$(__normalize_resource_data ${params[1]}) 190 | if test $what == "pods" && (contains_option "-A" || contains_option "--all-namespaces" ); then 191 | __top_all__ 192 | else 193 | kubectl "$@" 194 | fi;; 195 | 196 | "get" ) 197 | what=$(__normalize_resource_data ${params[1]}) 198 | if test $what == "events" && (contains_option "-A" || contains_option "--all-namespaces" ); then 199 | __get_events_all__ 200 | elif contains_option "-o"; then 201 | kubectl "$@" 202 | elif (contains_option "-A") || (contains_option "--all-namespaces"); then 203 | export FZF_DEFAULT_COMMAND="kubectl get $OBJ -A" 204 | if [[ "${SCOPED}" == " " ]]; then 205 | __get_obj_all__ $(echo $OBJ | base64) 206 | else 207 | __get_obj__ $(echo $OBJ | base64) 208 | fi 209 | elif contains_option "-n" || (test -z ${options[@]}); then 210 | if [[ "${SCOPED}" == " " ]]; then 211 | NS=$(kubectl "$@" -o jsonpath='{.items[*].metadata.namespace}' | sed 's/ /\n/g' | uniq) 212 | NAMESPACE=${NS:-$(kubectl "$@" -o jsonpath='{.metadata.namespace}' | sed 's/ /\n/g')} 213 | export FZF_DEFAULT_COMMAND="kubectl get $OBJ -A --field-selector metadata.namespace=${NAMESPACE}" 214 | __get_obj_all__ $(echo $OBJ | base64) 215 | else 216 | export FZF_DEFAULT_COMMAND="kubectl get $OBJ" 217 | unset SCOPED 218 | unset NONSCOPED 219 | __get_obj__ $(echo $OBJ | base64) 220 | fi 221 | fi 222 | ;; 223 | *) kubectl "$@";; 224 | esac 225 | } 226 | -------------------------------------------------------------------------------- /kui_start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Here you can add any commands you want to be executed before multi windows mode will be activated. 5 | # 6 | 7 | #tmuxp load default 8 | #tmuxp load dev stg prod 9 | -------------------------------------------------------------------------------- /tmux-profiles/default.yaml.init: -------------------------------------------------------------------------------- 1 | session_name: default 2 | windows: 3 | - focus: 'true' 4 | layout: 8313,253x71,0,0[253x63,0,0,103,253x7,0,64,104] 5 | options: 6 | automatic-rename: 'off' 7 | panes: 8 | - focus: 'true' 9 | shell_command: 10 | - export KUBECONFIG=~/.kube/.yml 11 | - export ENV_FZF_COLOR="bg+:34,preview-bg:236" 12 | - clear 13 | start_directory: $HOME 14 | window_name: 15 | - layout: ae24,253x71,0,0,105 16 | options: 17 | automatic-rename: 'off' 18 | panes: 19 | - focus: 'true' 20 | shell_command: 21 | - export KUBECONFIG=~/.kube/.yml 22 | - export ENV_FZF_COLOR="bg+:129,preview-bg:236" 23 | - clear 24 | start_directory: $HOME 25 | window_name: 26 | - layout: a245,800x600,0,0,106 27 | options: 28 | automatic-rename: 'off' 29 | panes: 30 | - focus: 'true' 31 | shell_command: 32 | - export KUBECONFIG=~/.kube/.yml 33 | - export ENV_FZF_COLOR="bg+:197,preview-bg:236" 34 | - clear 35 | start_directory: $HOME 36 | window_name: 37 | -------------------------------------------------------------------------------- /tmux-profiles/dev.yaml.init: -------------------------------------------------------------------------------- 1 | session_name: 'Dev' 2 | shell_command_before: 3 | - export KUBECONFIG= 4 | - export ENV_FZF_COLOR="bg+:34,preview-bg:236" 5 | options: 6 | status-bg: "colour34" 7 | status-fg: "white" 8 | windows: 9 | - focus: 'true' 10 | layout: b75d,253x71,0,0,0 11 | options: 12 | automatic-rename: 'off' 13 | panes: 14 | - focus: 'true' 15 | shell_command: k get pods -A 16 | start_directory: $HOME 17 | window_name: pods 18 | - layout: b75e,253x71,0,0,1 19 | options: 20 | automatic-rename: 'off' 21 | panes: 22 | - focus: 'true' 23 | shell_command: k get deploy -A 24 | start_directory: $HOME 25 | window_name: deployments 26 | - layout: b75f,253x71,0,0,2 27 | options: 28 | automatic-rename: 'off' 29 | panes: 30 | - focus: 'true' 31 | shell_command: k get ingress -A 32 | start_directory: $HOME 33 | window_name: ingress 34 | - layout: b780,125x71,0,0,3 35 | options: 36 | automatic-rename: 'off' 37 | panes: 38 | - focus: 'true' 39 | shell_command: k get secrets -A 40 | start_directory: $HOME 41 | window_name: secrets 42 | - layout: b781,125x71,0,0,4 43 | options: 44 | automatic-rename: 'off' 45 | panes: 46 | - focus: 'true' 47 | shell_command: k get cm -A 48 | start_directory: $HOME 49 | window_name: ConfigMap 50 | - layout: b762,253x71,0,0,5 51 | options: 52 | automatic-rename: 'off' 53 | panes: 54 | - focus: 'true' 55 | shell_command: k logs 56 | start_directory: $HOME 57 | window_name: logs 58 | - layout: b763,253x71,0,0,6 59 | options: 60 | automatic-rename: 'off' 61 | panes: 62 | - focus: 'true' 63 | shell_command: k get svc -A 64 | start_directory: $HOME 65 | window_name: services 66 | - layout: b784,125x71,0,0,7 67 | options: 68 | automatic-rename: 'off' 69 | panes: 70 | - focus: 'true' 71 | shell_command: k get pv 72 | start_directory: $HOME 73 | window_name: PV 74 | - layout: b785,125x71,0,0,8 75 | options: 76 | automatic-rename: 'off' 77 | panes: 78 | - focus: 'true' 79 | shell_command: k get event -A 80 | start_directory: $HOME 81 | window_name: Events 82 | - layout: b766,253x71,0,0,9 83 | options: 84 | automatic-rename: 'off' 85 | panes: 86 | - focus: 'true' 87 | shell_command: kubectl get nodes 88 | start_directory: $HOME 89 | window_name: MAIN 90 | -------------------------------------------------------------------------------- /tmux-profiles/prod.yaml.init: -------------------------------------------------------------------------------- 1 | session_name: 'Prod' 2 | shell_command_before: 3 | - export KUBECONFIG= 4 | - export ENV_FZF_COLOR="bg+:197,preview-bg:236" 5 | options: 6 | status-bg: "colour197" 7 | status-fg: "white" 8 | windows: 9 | - focus: 'true' 10 | layout: b75d,253x71,0,0,0 11 | options: 12 | automatic-rename: 'off' 13 | panes: 14 | - focus: 'true' 15 | shell_command: k get pods -A 16 | start_directory: $HOME 17 | window_name: pods 18 | - layout: b75e,253x71,0,0,1 19 | options: 20 | automatic-rename: 'off' 21 | panes: 22 | - focus: 'true' 23 | shell_command: k get deploy -A 24 | start_directory: $HOME 25 | window_name: deployments 26 | - layout: b75f,253x71,0,0,2 27 | options: 28 | automatic-rename: 'off' 29 | panes: 30 | - focus: 'true' 31 | shell_command: k get ingress -A 32 | start_directory: $HOME 33 | window_name: ingress 34 | - layout: b780,125x71,0,0,3 35 | options: 36 | automatic-rename: 'off' 37 | panes: 38 | - focus: 'true' 39 | shell_command: k get secrets -A 40 | start_directory: $HOME 41 | window_name: secrets 42 | - layout: b781,125x71,0,0,4 43 | options: 44 | automatic-rename: 'off' 45 | panes: 46 | - focus: 'true' 47 | shell_command: k get cm -A 48 | start_directory: $HOME 49 | window_name: ConfigMap 50 | - layout: b762,253x71,0,0,5 51 | options: 52 | automatic-rename: 'off' 53 | panes: 54 | - focus: 'true' 55 | shell_command: k logs 56 | start_directory: $HOME 57 | window_name: logs 58 | - layout: b763,253x71,0,0,6 59 | options: 60 | automatic-rename: 'off' 61 | panes: 62 | - focus: 'true' 63 | shell_command: k get svc -A 64 | start_directory: $HOME 65 | window_name: services 66 | - layout: b784,125x71,0,0,7 67 | options: 68 | automatic-rename: 'off' 69 | panes: 70 | - focus: 'true' 71 | shell_command: k get pv 72 | start_directory: $HOME 73 | window_name: PV 74 | - layout: b785,125x71,0,0,8 75 | options: 76 | automatic-rename: 'off' 77 | panes: 78 | - focus: 'true' 79 | shell_command: k get event -A 80 | start_directory: $HOME 81 | window_name: Events 82 | - layout: b766,253x71,0,0,9 83 | options: 84 | automatic-rename: 'off' 85 | panes: 86 | - focus: 'true' 87 | shell_command: kubectl get nodes 88 | start_directory: $HOME 89 | window_name: MAIN 90 | -------------------------------------------------------------------------------- /tmux-profiles/stg.yaml.init: -------------------------------------------------------------------------------- 1 | session_name: 'Stg' 2 | shell_command_before: 3 | - export KUBECONFIG= 4 | - export ENV_FZF_COLOR="bg+:129,preview-bg:236" 5 | options: 6 | status-bg: "colour129" 7 | status-fg: "white" 8 | windows: 9 | - focus: 'true' 10 | layout: b75d,253x71,0,0,0 11 | options: 12 | automatic-rename: 'off' 13 | panes: 14 | - focus: 'true' 15 | shell_command: k get pods -A 16 | start_directory: $HOME 17 | window_name: pods 18 | - layout: b75e,253x71,0,0,1 19 | options: 20 | automatic-rename: 'off' 21 | panes: 22 | - focus: 'true' 23 | shell_command: k get deploy -A 24 | start_directory: $HOME 25 | window_name: deployments 26 | - layout: b75f,253x71,0,0,2 27 | options: 28 | automatic-rename: 'off' 29 | panes: 30 | - focus: 'true' 31 | shell_command: k get ingress -A 32 | start_directory: $HOME 33 | window_name: ingress 34 | - layout: b780,125x71,0,0,3 35 | options: 36 | automatic-rename: 'off' 37 | panes: 38 | - focus: 'true' 39 | shell_command: k get secrets -A 40 | start_directory: $HOME 41 | window_name: secrets 42 | - layout: b781,125x71,0,0,4 43 | options: 44 | automatic-rename: 'off' 45 | panes: 46 | - focus: 'true' 47 | shell_command: k get cm -A 48 | start_directory: $HOME 49 | window_name: ConfigMap 50 | - layout: b762,253x71,0,0,5 51 | options: 52 | automatic-rename: 'off' 53 | panes: 54 | - focus: 'true' 55 | shell_command: k logs 56 | start_directory: $HOME 57 | window_name: logs 58 | - layout: b763,253x71,0,0,6 59 | options: 60 | automatic-rename: 'off' 61 | panes: 62 | - focus: 'true' 63 | shell_command: k get svc -A 64 | start_directory: $HOME 65 | window_name: services 66 | - layout: b784,125x71,0,0,7 67 | options: 68 | automatic-rename: 'off' 69 | panes: 70 | - focus: 'true' 71 | shell_command: k get pv 72 | start_directory: $HOME 73 | window_name: PV 74 | - layout: b785,125x71,0,0,8 75 | options: 76 | automatic-rename: 'off' 77 | panes: 78 | - focus: 'true' 79 | shell_command: k get event -A 80 | start_directory: $HOME 81 | window_name: Events 82 | - layout: b766,253x71,0,0,9 83 | options: 84 | automatic-rename: 'off' 85 | panes: 86 | - focus: 'true' 87 | shell_command: kubectl get nodes 88 | start_directory: $HOME 89 | window_name: MAIN 90 | --------------------------------------------------------------------------------