|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
|
|
#
|
|
|
|
# Copyright (C) 2020, Maxim Lihachev, <envrm@yandex.ru>
|
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify it
|
|
|
|
# under the terms of the GNU General Public License as published by the Free
|
|
|
|
# Software Foundation, version 3.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#
|
|
|
|
|
|
|
|
: <<'MAN'
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
|
|
|
kubectl-compare allows to juxtapose kubernetes resources with any diff-like utilities.
|
|
|
|
|
|
|
|
=head1 USAGE
|
|
|
|
|
|
|
|
kubectl compare [-n|--namespace NAMESPACE] [-t|--type] [-e|--edit|-v|--visual] name1 name2
|
|
|
|
or
|
|
|
|
kubectl compare [-e|--edit|-v|--visual] namespace/type/name1 namespace/type/name2
|
|
|
|
or
|
|
|
|
kubectl compare [-e|--edit|-v|--visual] namespace/type/name1 namespace/type/name2 namespace/type/name3 ...
|
|
|
|
|
|
|
|
=head1 OPTIONS
|
|
|
|
|
|
|
|
-n --namespace Kubernetes namespace for search ('default' by default).
|
|
|
|
-t --type Kubernetes resource's type, e.g. pod, svc, configmap, etc ('pod' by default).
|
|
|
|
-e --edit, -v --visual Open diff in visual editor (e.g. vimdiff).
|
|
|
|
|
|
|
|
Set B<VISUAL_DIFF_CMD> environment variable or provide its value in script's
|
|
|
|
file (kubectl-compare) to specify utility which will be used.
|
|
|
|
|
|
|
|
To specify main diff program set B<DIFF_CMD> variable (its default value is I<'diff
|
|
|
|
-u --color=always'>).
|
|
|
|
|
|
|
|
Use something like I<diff3> to compare 3 manifests.
|
|
|
|
|
|
|
|
=head1 EXAMPLE
|
|
|
|
|
|
|
|
$ kubectl compare -n zookeeper -t pod zookeeper-0 zookeeper-1
|
|
|
|
$ kubectl compare -n zookeeper pod/zookeeper-0 pod/zookeeper-1
|
|
|
|
$ kubectl compare zookeeper/pod/zookeeper-0 zookeeper/pod/zookeeper-1
|
|
|
|
^ ^ ^
|
|
|
|
[namespace]---+ | |
|
|
|
|
[type]----+ |
|
|
|
|
[name]--+
|
|
|
|
|
|
|
|
$ kubectl compare zookeeper/pod/zookeeper-{0,1,2}
|
|
|
|
|
|
|
|
=head1 BUGS
|
|
|
|
|
|
|
|
If you find a bug, please report it at B<L<https://code.envrm.info/src/scripts-kubernetes>>.
|
|
|
|
|
|
|
|
=head1 AUTHORS
|
|
|
|
|
|
|
|
envrm B<L<https://code.envrm.info>>.
|
|
|
|
|
|
|
|
=cut
|
|
|
|
MAN
|
|
|
|
|
|
|
|
|
|
|
|
set -o pipefail
|
|
|
|
|
|
|
|
if [ -z "$DIFF_CMD" ]; then
|
|
|
|
DIFF_CMD="diff -u --color=always"
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ -z "$VISUAL_DIFF_CMD" ]; then
|
|
|
|
VISUAL_DIFF_CMD="vim -d --cmd 'autocmd BufRead * set filetype=yaml'"
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Default Kubernetes namespace
|
|
|
|
NAMESPACE=default
|
|
|
|
|
|
|
|
# Default Kubernetes resource
|
|
|
|
TYPE=pod
|
|
|
|
|
|
|
|
usage() {
|
|
|
|
sed -E -n '/^.*MAN/,/^MAN$/{//!p;}; /^MAN$/q' "$0" | sed -E 's/=head. |[LIBC]<|\b>*//g; /=cut/d'
|
|
|
|
exit "${1:-0}"
|
|
|
|
}
|
|
|
|
|
|
|
|
die() {
|
|
|
|
>&2 echo "ERROR: $*"
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
|
|
kubecmd() {
|
|
|
|
IFS='/' read -r -a item <<< "$(sed -E 's:^/|/$::g' <<<"$1")"
|
|
|
|
|
|
|
|
case ${#item[@]} in
|
|
|
|
1) kubectl_cmd="kubectl --namespace $NAMESPACE get $TYPE ${item[0]} -o yaml";;
|
|
|
|
2) kubectl_cmd="kubectl --namespace $NAMESPACE get ${item[0]} ${item[1]} -o yaml";;
|
|
|
|
3) kubectl_cmd="kubectl --namespace ${item[0]} get ${item[1]} ${item[2]} -o yaml";;
|
|
|
|
*) exit 1;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
echo "<(${kubectl_cmd[*]})"
|
|
|
|
}
|
|
|
|
|
|
|
|
#--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
POSITIONAL=()
|
|
|
|
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
|
|
key="$1"
|
|
|
|
|
|
|
|
case $key in
|
|
|
|
-h|--help) usage;;
|
|
|
|
-e|--edit|-v|--visual) DIFF_CMD=$VISUAL_DIFF_CMD; shift;;
|
|
|
|
-n|--namespace) NAMESPACE="$2"; shift; shift;;
|
|
|
|
-t|--type) TYPE="$2"; shift; shift;;
|
|
|
|
|
|
|
|
*) POSITIONAL+=("$1"); shift;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
|
|
|
|
set -- "${POSITIONAL[@]}"
|
|
|
|
|
|
|
|
diff_cmd=("$DIFF_CMD")
|
|
|
|
|
|
|
|
if [ $# -lt 2 ]; then
|
|
|
|
usage 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
for cmd in "$@"; do
|
|
|
|
diff_cmd+=($(kubecmd "$cmd")) || die "Excessive nestedness of Kubernetes resource: $cmd"
|
|
|
|
done
|
|
|
|
|
|
|
|
eval "${diff_cmd[*]}"
|
|
|
|
|