mirror of
https://github.com/koalaman/shellcheck.git
synced 2025-10-03 19:29:44 +08:00
Created _Footer (markdown)
441
_Footer.md
Normal file
441
_Footer.md
Normal file
@@ -0,0 +1,441 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#author: chuxiaowei@360.cn
|
||||||
|
#date: 2020.08.04
|
||||||
|
|
||||||
|
: ${HELM_MINIMUM_ACCEPTABLE_VERSION:='3.2.4'}
|
||||||
|
: ${ACTION_INFO_PATH:='./resources/info'}
|
||||||
|
: ${PACKAGE_VALUES_PATH:='./resources/values'}
|
||||||
|
: ${DOCKER_IMAGES_PATH:='./resources/dockerImages'}
|
||||||
|
: ${HELM_LOCAL_INSTALL_SHELL:='./resources/helm/install_helm.sh'}
|
||||||
|
|
||||||
|
# 版本比较辅助函数
|
||||||
|
VER_SPLIT_SED='s/\./ /g;s/\([[:digit:]]\)\([^[:digit:] ]\)/\1 \2/g;s/\([^[:digit:] ]\)\([[:digit:]]\)/\1 \2/g'
|
||||||
|
# Compare with one element of version components
|
||||||
|
_ver_cmp_1() {
|
||||||
|
[[ "$1" = "$2" ]] && return 0
|
||||||
|
if [[ -z "${1//[[:digit:]]/}" ]] && [[ -z "${2//[[:digit:]]/}" ]]; then
|
||||||
|
# Both $1 and $2 are numbers
|
||||||
|
# Using arithmetic comparison
|
||||||
|
(( $1 > $2 )) && return 1
|
||||||
|
(( $1 < $2 )) && return 2
|
||||||
|
else
|
||||||
|
# Either or both are not numbers, containing non-digit characters
|
||||||
|
# Using string comparison
|
||||||
|
[[ "$1" > "$2" ]] && return 1
|
||||||
|
[[ "$1" < "$2" ]] && return 2
|
||||||
|
fi
|
||||||
|
# This should not be happening
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ver_cmp() {
|
||||||
|
local A B i result
|
||||||
|
A=($(sed "$VER_SPLIT_SED" <<< "$1"))
|
||||||
|
B=($(sed "$VER_SPLIT_SED" <<< "$2"))
|
||||||
|
i=0
|
||||||
|
while (( i < ${#A[@]} )) && (( i < ${#B[@]})); do
|
||||||
|
_ver_cmp_1 "${A[i]}" "${B[i]}"
|
||||||
|
result=$?
|
||||||
|
[[ $result =~ [12] ]] && return $result
|
||||||
|
let i++
|
||||||
|
done
|
||||||
|
# Which has more, then it is the newer version
|
||||||
|
_ver_cmp_1 "${#A[i]}" "${#B[i]}"
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
# 解析json
|
||||||
|
parse_json(){
|
||||||
|
# {"target_version":"1.1.0","current_version":"1.0.0"}
|
||||||
|
local keystr="$2\":\""
|
||||||
|
echo `cat "$1" | sed "s/{\"//g" | sed "s/\"}//g" | sed "s/\",\"/+++/g" | tr "+++" "\n" | grep "$keystr" | sed "s/$keystr//g"`
|
||||||
|
}
|
||||||
|
|
||||||
|
# log
|
||||||
|
log() {
|
||||||
|
local msg=''
|
||||||
|
for m in $@;
|
||||||
|
do
|
||||||
|
msg="$msg $m"
|
||||||
|
done
|
||||||
|
echo -e "[---info-->>>] $msg"
|
||||||
|
}
|
||||||
|
|
||||||
|
logerr() {
|
||||||
|
local msg=''
|
||||||
|
for m in $@;
|
||||||
|
do
|
||||||
|
msg="$msg $m"
|
||||||
|
done
|
||||||
|
echo -e "[--error-->>>] $msg"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_absolute_path() {
|
||||||
|
local path="$(dirname $0)/$(echo $1 | sed "s/\.\///g")"
|
||||||
|
echo $path
|
||||||
|
}
|
||||||
|
|
||||||
|
# helm 安装
|
||||||
|
helm_install() {
|
||||||
|
read -p "helm离线安装使用资源包自带的version 3.2.4 版本,在线安装将联网拉取线上最新版本。是否离线安装?(y/n [y]): " offline
|
||||||
|
echo $offline
|
||||||
|
if [[ "$offline" == "y" || "$offline" == "Y" || "$offline" == `echo -e "\n"` ]];then
|
||||||
|
log "执行helm安装脚本..."
|
||||||
|
local shellPath=$(get_absolute_path $HELM_LOCAL_INSTALL_SHELL)
|
||||||
|
chmod 700 $shellPath
|
||||||
|
eval $shellPath
|
||||||
|
else
|
||||||
|
local helmInstallShellUrl='https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3'
|
||||||
|
log "准备拉取helm安装脚本: $helmInstallShellUrl"
|
||||||
|
curl -fsSL -o get_helm.sh $helmInstallShellUrl
|
||||||
|
log "为helm安装脚本赋权..."
|
||||||
|
chmod 700 get_helm.sh
|
||||||
|
log "执行helm安装脚本..."
|
||||||
|
./get_helm.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
local version=$(get_helm_version)
|
||||||
|
if [ "$version" != "" ];then
|
||||||
|
log "helm install success. current Version : $version"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 获取helm 版本
|
||||||
|
get_helm_version() {
|
||||||
|
local helmVersionInfo=$(helm version | grep version.BuildInfo)
|
||||||
|
local info=$(echo $helmVersionInfo)
|
||||||
|
if [ "$info" == "" ];then
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
# helmVersion=$(echo $info | grep -o '".*"' | sed 's/"//g')
|
||||||
|
# helmVersion=${helmVersion%%,*}
|
||||||
|
local helmVersion=$(helm version --template="{{ .Version }}")
|
||||||
|
helmVersion=$(echo $helmVersion | sed 's/v//g')
|
||||||
|
echo "$helmVersion"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# 环境检查,检查helm是否安装,版本检查
|
||||||
|
check_helm_env() {
|
||||||
|
# 1.检查kubectl
|
||||||
|
local kubeVersion=$(kubectl version)
|
||||||
|
if [ "$(echo $kubeVersion | grep 'command not found')" != "" ];then
|
||||||
|
logerr "未检测到 kubectl命令,请安装 kubectl 命令行工具后重试。"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
local kubeContextInfo=$(kubectl config current-context)
|
||||||
|
if [ "$(echo $kubeContextInfo | grep 'current-context is not set')" != "" ];then
|
||||||
|
logerr "未检测到 kubectl config 配置,请在配置kubectl config后重试."
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2.检查helm
|
||||||
|
local version=$(get_helm_version)
|
||||||
|
if [ $version == "" ];then
|
||||||
|
log "can not find helm command... try install."
|
||||||
|
local infoPath=$(get_absolute_path $ACTION_INFO_PATH)
|
||||||
|
local actionType=$(parse_json $infoPath "action_type")
|
||||||
|
if [[ $actionType == "install" ]];then
|
||||||
|
helm_install
|
||||||
|
version=$(get_helm_version)
|
||||||
|
else
|
||||||
|
exit 4
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "current helm version: $version"
|
||||||
|
set +e
|
||||||
|
ver_cmp "$version" "$HELM_MINIMUM_ACCEPTABLE_VERSION"
|
||||||
|
cmp_res=$?
|
||||||
|
set -e
|
||||||
|
if [ $cmp_res == 2 ] # <
|
||||||
|
then
|
||||||
|
log "当前版本太低,请升级helm版本,helm version 不低于 v$HELM_MINIMUM_ACCEPTABLE_VERSION ."
|
||||||
|
read -p "是否立即升级?(y/n [y]): " flag
|
||||||
|
if [[ "$flag" == "y" || "$flag" == "Y" || "$flag" == `echo -e "\n"` ]];then
|
||||||
|
helm_install
|
||||||
|
else
|
||||||
|
log "程序已退出,请升级 helm 版本后重试。"
|
||||||
|
exit 4
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
package_action_confirmation() {
|
||||||
|
local infoPath=$(get_absolute_path $ACTION_INFO_PATH)
|
||||||
|
local releaseName=$(parse_json $infoPath "release_name")
|
||||||
|
local actionType=$(parse_json $infoPath "action_type")
|
||||||
|
local targetVersion=$(parse_json $infoPath "target_version")
|
||||||
|
local changeLog=$(parse_json $infoPath "change_log")
|
||||||
|
log "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||||
|
log "\t Release Name: $releaseName"
|
||||||
|
log "\t Target Version: $targetVersion"
|
||||||
|
log "\t Action Type: $actionType"
|
||||||
|
log "\t Change Log: $changeLog"
|
||||||
|
log "\t Another K8S Nodes: $K8S_IPs"
|
||||||
|
log "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||||
|
local flag=""
|
||||||
|
read -p "请确认上述关于安装包任务的相关信息,是否立即执行?(y/n [y]): " flag
|
||||||
|
if [[ "$flag" == "y" || "$flag" == "Y" || "$flag" == `echo -e "\n"` ]];then
|
||||||
|
return
|
||||||
|
else
|
||||||
|
log "已取消【立即执行】操作,程序已退出。"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
make_docker_image_dir(){
|
||||||
|
|
||||||
|
mkdir -p /root/local_images/images/
|
||||||
|
|
||||||
|
# 确保存镜像的文件夹存在
|
||||||
|
if [ $# -lt 1 ];then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 同步到其他节点
|
||||||
|
for i in $@;
|
||||||
|
do
|
||||||
|
ssh -p 22 -nq $i 'mkdir -p /root/local_images/images/'
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 拉镜像
|
||||||
|
pull_docker_images() {
|
||||||
|
|
||||||
|
read -p "是否需要为安装拉取镜像, 并同步到其他节点?(y/n [n]): " flag
|
||||||
|
if [[ "$flag" == "y" || "$flag" == "Y" ]];then
|
||||||
|
log "即将拉取镜像..."
|
||||||
|
else
|
||||||
|
log "跳过【镜像拉取】"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local tmp_dockerImage='dockerImage.tmp'
|
||||||
|
if [ -f $tmp_dockerImage ];then
|
||||||
|
rm -rf $tmp_dockerImage
|
||||||
|
fi
|
||||||
|
local dockerImagesPath=$(get_absolute_path $DOCKER_IMAGES_PATH)
|
||||||
|
local content=$(sort -n $dockerImagesPath | uniq >> $tmp_dockerImage)
|
||||||
|
imagesCount=0
|
||||||
|
log "+++++++++++++++++++++++ 将要拉取同步下列镜像 +++++++++++++++++++++++++"
|
||||||
|
for LINE in `cat "./$tmp_dockerImage"`
|
||||||
|
do
|
||||||
|
log "\t$LINE"
|
||||||
|
let imagesCount+=1
|
||||||
|
done
|
||||||
|
log "++++++++++++++++++++++++ 共 $imagesCount 个镜像++++++++++++++++++++++++++++"
|
||||||
|
|
||||||
|
make_docker_image_dir $@
|
||||||
|
|
||||||
|
imagesCount=0
|
||||||
|
|
||||||
|
# 并发执,控制最大并发数为10
|
||||||
|
start_time=`date +%s`
|
||||||
|
tmp_fifofile="/tmp/$$.fifo" # 已进程号命令创建临时文件
|
||||||
|
mkfifo $tmp_fifofile
|
||||||
|
exec 6<>$tmp_fifofile # 将FD6指向FIFO类型
|
||||||
|
rm $tmp_fifofile
|
||||||
|
thread_num=10 #最大进程数
|
||||||
|
for ((i=0;i<${thread_num};i++));do
|
||||||
|
echo >&6
|
||||||
|
done
|
||||||
|
|
||||||
|
for LINE in `cat "./$tmp_dockerImage"`
|
||||||
|
do
|
||||||
|
read -u6
|
||||||
|
{
|
||||||
|
local imageAddr=`echo $LINE | sed "s/'//g"`
|
||||||
|
local imageName=`basename $imageAddr`
|
||||||
|
docker pull $imageAddr
|
||||||
|
docker save $imageAddr -o /root/local_images/images/$imageName.tar
|
||||||
|
log "当前节点 : $imageName 拉取成功"
|
||||||
|
|
||||||
|
# 检查入参是否有传入其他节点
|
||||||
|
if [ $# -lt 1 ];then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 同步到其他节点
|
||||||
|
for i in $@;
|
||||||
|
do
|
||||||
|
if ssh -p 22 -nq $i test -e "/root/local_images/images/$imageName.tar" ;then
|
||||||
|
log "$i : $imageName 已存在"
|
||||||
|
else
|
||||||
|
log "准备同步 $i : $imageName"
|
||||||
|
rsync -avz --progress /root/local_images/images/$imageName.tar $i:/root/local_images/images/$imageName.tar
|
||||||
|
fi
|
||||||
|
log "$i : docker will load $imageName"
|
||||||
|
ssh -p 22 -nq $i "docker load -i /root/local_images/images/$imageName.tar"
|
||||||
|
log "$i : $imageName 同步、加载完成"
|
||||||
|
done
|
||||||
|
let imagesCount+=1
|
||||||
|
echo >&6
|
||||||
|
} &
|
||||||
|
done
|
||||||
|
wait
|
||||||
|
stop_time=`date +%s`
|
||||||
|
log "拉取同步镜像共耗时:`expr $stop_time - $start_time`"
|
||||||
|
|
||||||
|
exec 6<&- #关闭文件描述符的读
|
||||||
|
exec 6>&- #关闭文件描述符的写
|
||||||
|
rm "./$tmp_dockerImage"
|
||||||
|
}
|
||||||
|
|
||||||
|
package_install() {
|
||||||
|
local infoPath=$(get_absolute_path $ACTION_INFO_PATH)
|
||||||
|
local releaseName=$(parse_json $infoPath "release_name")
|
||||||
|
local packagePath=$(parse_json $infoPath "package_path")
|
||||||
|
local actionType=$(parse_json $infoPath "action_type")
|
||||||
|
|
||||||
|
local actionCMD=''
|
||||||
|
case "$actionType" in
|
||||||
|
'install') actionCMD='upgrade --install' ;;
|
||||||
|
'upgrade') actionCMD='upgrade --install' ;;
|
||||||
|
'rollback') actionCMD='upgrade' ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
packagePath=$(get_absolute_path $packagePath)
|
||||||
|
|
||||||
|
local valuesDir=$(get_absolute_path $PACKAGE_VALUES_PATH)
|
||||||
|
local valuesCmd=''
|
||||||
|
for j in `ls $valuesDir`;
|
||||||
|
do
|
||||||
|
valuesCmd="$valuesCmd -f $valuesDir/$j"
|
||||||
|
done
|
||||||
|
|
||||||
|
local HELM_CMD="helm $actionCMD $releaseName $packagePath $valuesCmd"
|
||||||
|
log "执行命令: $HELM_CMD"
|
||||||
|
eval $HELM_CMD
|
||||||
|
}
|
||||||
|
|
||||||
|
jobs_install_cmd() {
|
||||||
|
local infoPath=$(get_absolute_path $ACTION_INFO_PATH)
|
||||||
|
local packagePath=$(parse_json $infoPath "job_package_path")
|
||||||
|
local actionType=$(parse_json $infoPath "action_type")
|
||||||
|
|
||||||
|
if [[ "$actionType" == "rollback" ]];then
|
||||||
|
log "当前执行的是回滚操作,job暂不执行"
|
||||||
|
echo ""
|
||||||
|
else if [[ "$packagePath" == "" ]];then
|
||||||
|
log "未发现有需要执行的jobs"
|
||||||
|
echo "
|
||||||
|
else
|
||||||
|
local pwdPath=`pwd`
|
||||||
|
local releaseName=`basename $pwdPath`
|
||||||
|
releaseName="$releaseName-jobs"
|
||||||
|
packagePath=$(get_absolute_path $packagePath)
|
||||||
|
|
||||||
|
local valuesDir=$(get_absolute_path $PACKAGE_VALUES_PATH)
|
||||||
|
local valuesCmd=''
|
||||||
|
for j in `ls $valuesDir`;
|
||||||
|
do
|
||||||
|
valuesCmd="$valuesCmd -f $valuesDir/$j"
|
||||||
|
done
|
||||||
|
|
||||||
|
local HELM_CMD="helm install $releaseName $packagePath $valuesCmd"
|
||||||
|
echo $HELM_CMD
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
jobs_install() {
|
||||||
|
|
||||||
|
local HELM_CMD=$(jobs_install_cmd)
|
||||||
|
|
||||||
|
if [[ "$HELM_CMD" == "" ]];then
|
||||||
|
log "离线包版本job检查完毕"
|
||||||
|
else
|
||||||
|
read -p "检测到离线包中有 jobs 可以执行,是否需要执行离线包中的 jobs? (m:手动模式)(y/m/n [n]): " flag
|
||||||
|
if [[ "$flag" == "y" || "$flag" == "Y" || "$flag" == "m" || "$flag" == "M" ]];then
|
||||||
|
log "开始执行版本任务..."
|
||||||
|
HELM_CMD="$HELM_CMD --set tags.all=true"
|
||||||
|
if [[ "$flag" == "m" || "$flag" == "M" ]];then
|
||||||
|
HELM_CMD="$HELM_CMD --set migration.manual=true"
|
||||||
|
fi
|
||||||
|
log "执行命令: $HELM_CMD"
|
||||||
|
eval $HELM_CMD
|
||||||
|
else
|
||||||
|
log "跳过【jobs 执行】"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fail_trap() {
|
||||||
|
result=$?
|
||||||
|
if [ "$result" != "0" ]; then
|
||||||
|
case "$result" in
|
||||||
|
"3") echo "请确保安装 kubectl 命令行工具,以及正确配置集群环境." ;;
|
||||||
|
"4") echo "请确保安装 helm 命令行工具,以及版本不低于 $HELM_MINIMUM_ACCEPTABLE_VERSION ." ;;
|
||||||
|
esac
|
||||||
|
if [[ -n "$INPUT_ARGUMENTS" ]]; then
|
||||||
|
logerr "Failed to install package with the arguments provided: $INPUT_ARGUMENTS"
|
||||||
|
help
|
||||||
|
else
|
||||||
|
logerr "Failed to install package."
|
||||||
|
fi
|
||||||
|
echo -e "\tFor support, read the file Readme.md"
|
||||||
|
fi
|
||||||
|
exit $result
|
||||||
|
}
|
||||||
|
|
||||||
|
help () {
|
||||||
|
echo "Accepted cli arguments are:"
|
||||||
|
echo -e "\t[--help | -h ] ->> prints this help"
|
||||||
|
echo -e "\t[--install | -i <k8s集群地址> ] . When it not defined, the dcoker images cannot be synchronized to other nodes."
|
||||||
|
echo -e "\te.g. --install k8s2 k8s3 k8s4 k8s5 or -i k8s2 k8s3 k8s4 k8s5"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
|
||||||
|
# 1.检查执行环境
|
||||||
|
log "检查相关执行环境..."
|
||||||
|
check_helm_env
|
||||||
|
|
||||||
|
# 2.离线任务信息确认
|
||||||
|
log "离线任务信息确认..."
|
||||||
|
package_action_confirmation
|
||||||
|
|
||||||
|
# 3.拉取docker镜像
|
||||||
|
log "为服务安装拉取相关镜像..."
|
||||||
|
pull_docker_images $@
|
||||||
|
log "拉取相关镜像操作已完成"
|
||||||
|
|
||||||
|
# 4.执行版本任务
|
||||||
|
log "检查版本job..."
|
||||||
|
jobs_install
|
||||||
|
|
||||||
|
# 5.执行版本操作
|
||||||
|
log "开始安装离线包..."
|
||||||
|
package_install
|
||||||
|
|
||||||
|
log "安装包执行完毕."
|
||||||
|
}
|
||||||
|
|
||||||
|
trap "fail_trap" EXIT
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# 解析参数
|
||||||
|
export INPUT_ARGUMENTS="${@}"
|
||||||
|
set -u
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
'--install'|-i)
|
||||||
|
shift
|
||||||
|
if [[ $# -ne 0 ]]; then
|
||||||
|
export K8S_IPs=$@
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
'--help'|-h)
|
||||||
|
help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*) exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
break
|
||||||
|
done
|
||||||
|
set +u
|
||||||
|
|
||||||
|
|
||||||
|
main $K8S_IPs
|
Reference in New Issue
Block a user