Skip to content

Instantly share code, notes, and snippets.

@ravilach
Created February 4, 2022 21:58
Show Gist options
  • Save ravilach/867c340379683ef0e40eb94a2fbefbe5 to your computer and use it in GitHub Desktop.
Save ravilach/867c340379683ef0e40eb94a2fbefbe5 to your computer and use it in GitHub Desktop.
Shipa Support Bundler
#!/usr/bin/env bash
usage() {
local -r _exitCode="${1}"
local -r _errorMessage="${2}"
if [[ -n "${_errorMessage}" ]]; then
printf >&2 "[ERROR] %s\n\n" "${_errorMessage}"
fi
echo " Connects to a Kubernetes cluster, pulls a diagnostic information and creates a bundle for Shipa Support."
echo >&2 " Usage: $0 [-o output_base_dir] [-s control_plan_namespace] [-m managed_namespace_1 managed_namespace_2 managed_namespace_n...] [-h]"
echo >&2 -e "\t-o | --out output_base_dir [Optional] Base directory to store the diagnostics data in. Defaults to the current directory."
echo >&2 -e "\t-s | --system control_plan_namespace [Optional] The name of the Shipa control plane namespace. Only applicable to self-hosted installation. Defaults to shipa-system."
echo >&2 -e "\t-m | --managed managed_namespace [Optional] The name of the Shipa managed namespace(s). Space separated list. Can be provided more than once. Defaults to shipa."
echo >&2 -e "\t-h | --help Print this message"
echo >&2 ""
echo >&2 " Example:"
echo >&2 -e "\t\t$0 --out /tmp/diagnostics --system none --managed my-framework-namespace"
exit ${_exitCode}
}
get_resource_diagnostics() {
local -r _target_namespace="${1}"
local -r _resource_type_long="${2}"
local -r _show_wide="${3:-"false"}"
local -r _resource_type="$(echo "${_resource_type_long}" | awk -F'.' '{print $1}')"
[[ "${_show_wide}" != "false" ]] && _flag="-o wide"
echo "" | tee -a ${GENERAL}
echo "[INFO] ${_target_namespace} ${_resource_type} (details in ${_target_namespace}-${_resource_type}.yaml):" | tee -a ${GENERAL}
kubectl get ${_resource_type_long} -n ${_target_namespace} ${_flag} 2>&1 | tee -a ${GENERAL}
kubectl get ${_resource_type_long} -n ${_target_namespace} -o yaml 2>&1 >${_target_namespace}-${_resource_type}.yaml
}
get_pod_logs() {
local -r _target_namespace="${1}"
echo "" | tee -a ${GENERAL}
echo "[INFO] Pulling ${_target_namespace} pod logs and storing them under ${_target_namespace}-pod-logs directory" | tee -a ${GENERAL}
mkdir -p ${_target_namespace}-pod-logs
pushd ${_target_namespace}-pod-logs >/dev/null
for _pod in $(kubectl get pods -n ${_target_namespace} -o name); do
for _container in $(kubectl get ${_pod} -n ${_target_namespace} -o jsonpath='{range .spec.containers[*]}{@.name} {end}{range .spec.initContainers[*]}{@.name} {end}'); do
echo "[INFO] Pulling logs for ${_pod}/${_container}" | tee -a ${GENERAL}
kubectl logs -n ${_target_namespace} ${_pod} -c ${_container} 2>&1 >"${_pod//\//__}__${_container}.log"
done
done
popd >/dev/null
}
get_namespace_diagnostics() {
local -r _target_namespace="${1}"
echo "" | tee -a ${GENERAL}
kubectl get ns ${_target_namespace} 2>/dev/null && NS_FOUND="true" || NS_FOUND="false"
if [[ "${NS_FOUND}" == "true" ]]; then
echo "[INFO] Found '${_target_namespace}' namespace." | tee -a ${GENERAL}
else
echo "[INFO] '${_target_namespace}' namespace does not exist. Skipping ${_target_namespace} checks." | tee -a ${GENERAL}
return
fi
mkdir -p ${_target_namespace}
pushd ${_target_namespace} >/dev/null
get_resource_diagnostics ${_target_namespace} events
get_resource_diagnostics ${_target_namespace} deployments.apps
get_resource_diagnostics ${_target_namespace} daemonsets.apps
get_resource_diagnostics ${_target_namespace} statefulsets.apps
get_resource_diagnostics ${_target_namespace} replicasets.apps
get_resource_diagnostics ${_target_namespace} services
get_resource_diagnostics ${_target_namespace} ingresses.networking.k8s.io
get_resource_diagnostics ${_target_namespace} jobs.batch wide
get_resource_diagnostics ${_target_namespace} pods wide
get_pod_logs ${_target_namespace}
popd >/dev/null
}
SHIPA_SYSTEM="${SHIPA_SYSTEM:-"shipa-system"}"
DIAGNOSTICS_DIR=${DIAGNOSTICS_DIR:-"./"}
MANAGED_NAMESPACES=""
while [ -n "$1" ]; do
case "$1" in
-o | --out)
shift
DIAGNOSTICS_DIR="${1}"
;;
-s | --system)
shift
SHIPA_SYSTEM="${1}"
;;
-m | --managed)
while [[ -n "${2}" && ! "${2}" =~ ^- ]]; do
shift
MANAGED_NAMESPACES+=" ${1}"
done
;;
-h | --help)
usage 0
;;
*)
usage 1 "Invalid parameter '$1'"
;;
esac
shift
done
# get full name of the output root directory
DIAGNOSTICS_DIR="$(cd "$(dirname "${DIAGNOSTICS_DIR}")" >/dev/null 2>&1 && pwd)"
# set default managed namespace and ensure list has unique entries only
MANAGED_NAMESPACES="$(echo "${MANAGED_NAMESPACES:-"shipa"}" | sed 's/^ //; s/ /\n/g' | awk '!a[$0]++' | grep -v "${SHIPA_SYSTEM}\\|cert-manager")"
type -p kubectl || (
usage 1 "kubectl cannot be found on your system. Ensure that kubectl is installed and on your path."
)
type -p tar && CREATE_BUNDLE="true" || (
echo >&2 "[ERROR] tar cannot be found on your system. Logs will be collected, but the support bundle will not be created."
CREATE_BUNDLE="false"
)
mkdir -p ${DIAGNOSTICS_DIR}
if [[ ! -d "${DIAGNOSTICS_DIR}" ]]; then
usage 1 "${DIAGNOSTICS_DIR} does not exist and could not be created."
fi
export OUT_DIR="$(echo "shipa-diagnostics-$(date +%s)")"
echo "[INFO] Creating diagnostics sub directory '${OUT_DIR}'."
pushd ${DIAGNOSTICS_DIR} >/dev/null
mkdir -p "${OUT_DIR}"
pushd "${OUT_DIR}" >/dev/null
GENERAL="${PWD}/overview.log"
if [[ "$(basename $PWD)" != "${OUT_DIR}" ]]; then
popd >/dev/null
popd >/dev/null
usage 1 "Unable to create diagnostics sub directory '${OUT_DIR}'."
fi
rm -rf *
echo "[INFO] Testing connection to cluster." | tee -a ${GENERAL}
kubectl get ns 2>&1 >/dev/null
if [[ $? -ne 0 ]]; then
popd >/dev/null
popd >/dev/null
usage 1 "Could not connect to cluster with context '$(kubectl config current-context)'."
fi
echo "[INFO] Using kubectl context '$(kubectl config current-context)'." | tee -a ${GENERAL}
for _target_namespace in ${SHIPA_SYSTEM} cert-manager ${MANAGED_NAMESPACES}; do
get_namespace_diagnostics ${_target_namespace}
done
echo ""
popd >/dev/null
if [[ "${CREATE_BUNDLE}" == "true" ]]; then
tar -zcf ${OUT_DIR}.tar.gz ${OUT_DIR} && echo "[INFO] Support bundle was created as ${OUT_DIR}.tar.gz" || echo >&2 "[ERROR] Could not create support bundle."
fi
popd >/dev/null
echo "[INFO] Diagnostics data was sent to ${DIAGNOSTICS_DIR}/${OUT_DIR}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment