Skip to content

Commit

Permalink
Merge pull request #2 from predatorray/0.0.x
Browse files Browse the repository at this point in the history
Options `-it` are deprecated & Pod names can be read from a file using  `-f`
  • Loading branch information
predatorray authored Mar 8, 2020
2 parents b0775e1 + 29e5ba3 commit a413c35
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
NAME=kubectl-tmux-exec
VERSION=0.0.2
VERSION=0.0.3

OUTPUT_DIR=output
RELEASE_FILE_NAME=$(NAME)-$(VERSION).tar.gz
Expand Down
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# kubectl-tmux-exec

![homebrew](https://img.shields.io/badge/homebrew-0.0.2-orange)
![homebrew](https://img.shields.io/badge/homebrew-0.0.3-orange)
![license](https://img.shields.io/badge/license-MIT-green)

A kubectl plugin that uses [Tmux](https://github.com/tmux/tmux) to multiplex commands to pods.
Expand All @@ -9,12 +9,12 @@ A kubectl plugin that uses [Tmux](https://github.com/tmux/tmux) to multiplex com

It is to `kubectl exec` as `csshX` or `pssh` is to `ssh`.

Instead of `exec bash` into multiple pod's containers one-at-a-time, like `kubectl exec -it pod{N} /bin/bash`.
Instead of `exec bash` into multiple pod's containers one-at-a-time, like `kubectl exec pod{N} /bin/bash`.

You can now use

```sh
kubectl tmux-exec -it -l app=nginx /bin/bash
kubectl tmux-exec -l app=nginx /bin/bash
```

# Installation via Homebrew
Expand Down Expand Up @@ -68,11 +68,9 @@ The `tmux-exec` is similar to `exec`, except that it requires label selectors wh
To `bash` into all pod containers that share some common labels, `foo=bar` for instance.

```sh
kubectl tmux-exec -it -l foo=bar /bin/bash
kubectl tmux-exec -l foo=bar /bin/bash
```

It should be noted that the `-i` / `--stdin` and `-t` / `--tty` options must both be turned on when you are trying to initiate an interactive session. If not, there will not be any errors. Instead, the `tmux` process simply exits because the `exec`-ed command exits due to no inputs.

After you have successfully `bash`-ed into your selected containers, a Tmux window is opened actually, where each pane displays the execution result of each pod's container. Your keyboard inputs will be synchronized to all those panes.

If you are not familar with Tmux, you can have a look at tmux's man page or online tutorials. Or you can see the cheatsheet below, which will be sufficient I think.
Expand Down
60 changes: 39 additions & 21 deletions bin/kubectl-tmux_exec
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,24 @@ Examples:
${PROG_NAME} -l app=nginx -- tail -f /var/log/nginx/access.log
# Open bash terminals that attach to 'nginx' containers of all nginx pods
${PROG_NAME} -l app=nginx -c nginx -it /bin/bash
${PROG_NAME} -l app=nginx -c nginx /bin/bash
# Read pod names from a file instead of using a selector
${PROG_NAME} -f pods.txt /bin/bash
${PROG_NAME} -f - /bin/bash # read from stdin
Options:
-c, --container='': Container name. If omitted, the first container in the pod will be chosen
-i, --stdin=false: Pass stdin to the container
-t, --tty=false: Stdin is a TTY
-i, --stdin=true: Pass stdin to the container (deprecated, since it's enabled by default)
-t, --tty=true: Stdin is a TTY (deprecated, since it's enabled by default)
-l, --selector: Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)
-f, --file: Read pod names line-by-line from a file
--remain-on-exit=false: Remain Tmux window on exit
--select-layout=tiled: one of the five Tmux preset layouts: even-horizontal, even-vertical, main-horizontal,
--select-layout=tiled: One of the five Tmux preset layouts: even-horizontal, even-vertical, main-horizontal,
main-vertical, or tiled.
Usage:
${PROG_NAME} -l label [-c CONTAINER] [flags] -- COMMAND [args...]
${PROG_NAME} { -l label | -f pod-list-file } [-c CONTAINER] [flags] -- COMMAND [args...]
Use "kubectl options" for a list of global command-line options (applies to all commands).
EOF
Expand All @@ -91,6 +96,10 @@ function check_required_executables() {
done
}

function warn() {
echo >&2 'warn:' "$@"
}

function error_and_exit() {
echo >&2 'error:' "$@"
echo >&2 "Run '${PROG_NAME} --help' for more information on the command."
Expand Down Expand Up @@ -127,17 +136,16 @@ function array_contains() {

function main() {
local opts
opts=$(ggetopt -o hitc:l:"$(printf '%s:' "${KUBECTL_SHORT_OPTS[@]}")" --long \
help,stdin,tty,container:,selector:,remain-on-exit,select-layout:,"$(printf '%s:,' "${KUBECTL_LONG_OPTS[@]}")","$(printf '%s,' "${KUBECTL_NOARG_LONG_OPTS[@]}")" -- "$@")
opts=$(ggetopt -o hitc:l:f:"$(printf '%s:' "${KUBECTL_SHORT_OPTS[@]}")" --long \
help,stdin,tty,container:,selector:,remain-on-exit,select-layout:,file:,"$(printf '%s:,' "${KUBECTL_LONG_OPTS[@]}")","$(printf '%s,' "${KUBECTL_NOARG_LONG_OPTS[@]}")" -- "$@")
eval set -- $opts

local selector
local container_name
local opt_stdin=0
local opt_tty=0
local kubectl_opts=()
local remain_on_exit=0
local tmux_layout='tiled'
local pod_list_file
while [[ $# -gt 0 ]]; do
local opt="$1"
case "${opt}" in
Expand All @@ -150,10 +158,10 @@ function main() {
container_name="$1"
;;
-i|--stdin)
opt_stdin=1
warn "The option -i / --stdin is deprecated."
;;
-t|--tty)
opt_tty=1
warn "The option -t / --tty is deprecated."
;;
-l|--selector)
shift
Expand All @@ -166,6 +174,10 @@ function main() {
shift
tmux_layout="$1"
;;
-f|--file)
shift
pod_list_file="$1"
;;
--)
shift
break
Expand Down Expand Up @@ -204,8 +216,9 @@ function main() {
error_and_exit 'you must specify at least one command for the container'
fi

if [[ -z "${selector:-}" ]]; then
error_and_exit 'The label selector option is required: -l'
if ( [[ -z "${selector:-}" ]] && [[ -z "${pod_list_file:-}" ]] ) ||
( [[ ! -z "${selector:-}" ]] && [[ ! -z "${pod_list_file:-}" ]] ); then
error_and_exit 'you must either specify option -l or -f'
fi

if [[ -z "${tmux_layout}" ]] || ! array_contains "${tmux_layout}" "${TMUX_LAYOUTS[@]}"; then
Expand All @@ -214,13 +227,7 @@ function main() {

local commands=("$@")

local kubectl_exec_opts=''
if [[ "${opt_stdin}" -eq 1 ]]; then
kubectl_exec_opts="${kubectl_exec_opts} -i"
fi
if [[ "${opt_tty}" -eq 1 ]]; then
kubectl_exec_opts="${kubectl_exec_opts} -t"
fi
local kubectl_exec_opts='-i -t'
if [[ ! -z "${container_name:-}" ]]; then
kubectl_exec_opts="${kubectl_exec_opts} -c ${container_name}"
fi
Expand All @@ -234,11 +241,22 @@ function main() {
fi
done

if [[ ! -z "${pod_list_file:-}" ]] && [[ "${pod_list_file}" != '-' ]] && [[ ! -f "${pod_list_file}" ]]; then
error_and_exit "No such file or directory: ${pod_list_file}"
fi

local pods=()
while IFS='' read -r pod_name; do
if [[ -z "${pod_name}" ]]; then
continue
fi
pods+=("${pod_name}")
done < <(
kubectl ${kubectl_opts[@]:-} get pods -l "${selector}" -o custom-columns=':metadata.name' --no-headers
if [[ -z "${selector:-}" ]]; then
cat "${pod_list_file}"
else
kubectl ${kubectl_opts[@]:-} get pods -l "${selector}" -o custom-columns=':metadata.name' --no-headers
fi
)

if [[ "${#pods[@]}" -eq 0 ]]; then
Expand Down

0 comments on commit a413c35

Please sign in to comment.