deploy.sh脚本说明
使用场景说明
- 场景一:使用Jenkins构建生成的是软件包,如jar包,就使用脚本中的软件包部署场景,软件包部署会将构建出来的软件包上传到obs桶中,再使用新的jar包去升级CAE组件。
- 场景二:使用Jenkins构建生成的是镜像,就使用脚本中的镜像部署场景,镜像部署会将构建出来的镜像上传到swr镜像仓库中,再使用新的镜像去升级CAE组件。
脚本内容
#!/bin/bash
#------------ 必填参数 ------------------
# region名称
region=''
# 项目id
project_id=''
# 环境名称
environment_name=''
# 应用名称
application_name=''
# 组件名称
component_name=''
# 部署类型: 1. software 2. image software表示软件包部署, image表示镜像部署
deploy_type=''
#------------ 软件包部署场景必填参数 ---------------
# obsutil安装的可执行文件绝对路径
obsutil=''
# 存放软件包的obs桶名称
bucket_name=''
# 软件包在obs桶中的存放目录,默认是根目录,目录需要以/结尾,如果obs桶中没有这个目录,会自动创建出该目录
bucket_dir='/'
#------------ 镜像部署场景必填参数 ------------------
# swr组织名称
swr_organization=''
# AK 用于登录swr镜像仓库
AK=''
# swr登录密钥 用于登录swr镜像仓库
login_secret=''
#------------ 外部传入参数,不需要填,参考配置流水线构建任务中的流水线脚本参数build_target_name ------------------
# 软件包部署场景:构建出来的软件包名称,由外部build_target_name参数传入
software_package=''
# 镜像部署场景:构建后生成的镜像:镜像名称:版本名称,由外部build_target_name参数传入
machine_image_name=''
#必须传入一个参数,是软件包名称或镜像名称
#参数数量为1时,设置软件包名称或镜像名称
if [ $# == 1 ]; then
if [[ "$deploy_type" == "software" ]]; then
software_package=$1
elif [[ "$deploy_type" == "image" ]]; then
machine_image_name=$1
fi
else
echo "The number of external input parameters is not 1. Configure the pipeline script parameter build_target_name in the pipeline build task."
fi
# ---------------- 以下代码不用改动 -------------------
enterprise_project_id='0'
environment_id=''
application_id=''
component_id=''
function splitVersion() {
str=$1
right=${str##*.}
left=${str%.*}
if [ ${#str} -eq ${#left} ]; then
left=""
fi
}
function addVersion() {
v1=$1
res=`echo $v1|awk '{print int($0)}'`
if [ $res -gt 9998 ]; then
res=0
else
res=$(($res+1))
fi
}
# 升级版本号
# 版本号格式为:A.B.C或 A.B.C.D A、B、C、D均为整数,每个整数不大于9999
# 示例:1.0.0 -> 1.0.1;1.0.9999 -> 1.1.0
function upgradeVersion() {
left=$1
start=0
end=''
res=0
while ( [[ $res = 0 ]] && [ $start -lt 4 ] )
do
start=$(($start+1))
splitVersion $left
addVersion $right
if [ $start -gt 1 ]; then
end=`echo "$res.$end"`
else
end=`echo "$res$end"`
fi
done
if [ ${#left} -ne 0 ]; then
version="$left.$end"
else
version="$end"
fi
}
#获取组件升级的版本号
function upgradeComponentVersion() {
# 查询组件信息
component_details=`/usr/local/bin/hcloud CAE ShowComponent --cli-region="$region" --project_id="$project_id" --X-Enterprise-Project-ID="$enterprise_project_id" --X-Environment-ID="$environment_id" --application_id="$application_id" --component_id="$component_id"`
# 获取组件当前的版本号
version=`getJsonValuesByAwk "$component_details" "version" "defaultValue"`
version=`echo "$version" | cut -d '"' -f 2`
echo "current version: $version"
if [[ "$version" == "defaultValue" ]]; then
echo "get component details and get component version error"
echo "$component_details"
exit 126
fi
upgradeVersion $version
echo "upgrade version: $version"
}
# 软件包部署使用场景
function obs_software_upgrade() {
echo "upload jar to obs"
# 软件包上传到obs的地址,格式:obs://{桶名}{jar包在obs桶中的存放目录}
bucket_address="obs://$bucket_name$bucket_dir"
# 上传到obs的jar包链接,格式:https://{桶名}.obs.{region}.myhuaweicloud.com/{jar包在obs桶中的存放目录}/
obs_jar_url="https://$bucket_name.obs.$region.myhuaweicloud.com$bucket_dir$software_package"
echo "software_package url: $obs_jar_url"
# 将项目下构建生成的jar包上传到obs
obs_result=`"$obsutil" cp ./target/*.jar "$bucket_address"`
if [ $? -ne 0 ]; then
echo "obsutil upload software package error"
echo "$obs_result"
exit 126
fi
# 打印上传结果
echo "$obs_result"
# 升级组件
echo "upgrade component"
action_result=`/usr/local/bin/hcloud CAE ExecuteAction --cli-region="$region" --project_id="$project_id" --X-Enterprise-Project-ID="$enterprise_project_id" --X-Environment-ID="$environment_id" --application_id="$application_id" --component_id="$component_id" --api_version='v1' --kind='Action' --metadata.name='upgrade' --metadata.annotations.version="$version" --spec.source.type='softwarePackage' --spec.source.sub_type='BinObs' --spec.source.url="$obs_jar_url"`
}
# 生成秒级时间格式字符串,用于上传SWR镜像时,在版本后添加时间格式后缀
function generateTimeFormatString() {
ms=$(date +%s)
time=$(date -d @$ms "+%Y%m%d%H%M%S")
echo $time
}
# 镜像部署使用场景
function swr_image_upgrade() {
# 上传到swr的镜像仓库路径,格式为:[镜像仓库地址]/[组织名称]/[镜像名称:版本名称]
swr_image_url="swr.$region.myhuaweicloud.com/$swr_organization/$machine_image_name"
# swr 镜像仓库地址
swr_url="swr.$region.myhuaweicloud.com"
# swr镜像版本拼接时间格式字符串
time_format_string=`generateTimeFormatString`
swr_image_url="$swr_image_url.$time_format_string"
echo "upload image to swr"
docker tag "$machine_image_name" "$swr_image_url"
login_result=`docker login -u "$region"@"$AK" -p "$login_secret" "$swr_url"`
# 打印登录swr镜像仓库结果
#echo "$login_result"
push_result=`docker push "$swr_image_url"`
if [ $? -ne 0 ]; then
echo "docker push error"
echo "$push_result"
exit 126
fi
# 打印推送镜像结果
#echo "$push_result"
logout_result=`docker logout "$swr_url"`
# 打印退出登录swr镜像仓库的结果
#echo "$logout_result"
# 清除所有的历史记录,历史记录中可能会存在swr登录密钥信息,可以使用该命令清理所有的历史记录
#history -c
echo "upgrade component"
# 升级 image镜像组件
action_result=`/usr/local/bin/hcloud CAE ExecuteAction --cli-region="$region" --project_id="$project_id" --X-Enterprise-Project-ID="$enterprise_project_id" --X-Environment-ID="$environment_id" --application_id="$application_id" --component_id="$component_id" --api_version='v1' --kind='Action' --metadata.name='upgrade' --metadata.annotations.version="$version" --spec.source.type='image' --spec.source.url="$swr_image_url" `
}
### 方法简要说明:
### 1. 是查找一个字符串:带双引号的key。如果没找到,则直接返回defaultValue。
### 2. 查找最近的冒号,找到后认为值的部分开始了。
### 3. 如果有多个同名key,只打印第一个value
### 4. params: json, key, defaultValue
function getJsonValuesByAwk() {
awk -v json="$1" -v key="$2" -v defaultValue="$3" 'BEGIN{
foundKeyCount = 0
pos = match(json, "\""key"\"[ \\t]*?:[ \\t]*");
if (pos == 0) {if (foundKeyCount == 0) {print defaultValue;} exit 0;}
++foundKeyCount;
start = 0; stop = 0; layer = 0;
for (i = pos + length(key) + 1; i <= length(json); ++i) {
lastChar = substr(json, i - 1, 1)
currChar = substr(json, i, 1)
if (start <= 0) {
if (lastChar == ":") {
start = currChar == " " ? i + 1: i;
if (currChar == "{" || currChar == "[") {
layer = 1;
}
}
} else {
if (currChar == "{" || currChar == "[") {
++layer;
}
if (currChar == "}" || currChar == "]") {
--layer;
}
if ((currChar == "," || currChar == "}" || currChar == "]") && layer <= 0) {
stop = currChar == "," ? i : i + 1 + layer;
break;
}
}
}
if (start <= 0 || stop <= 0 || start > length(json) || stop > length(json) || start >= stop) {
if (foundKeyCount == 0) {print defaultValue;} exit 0;
} else {
print substr(json, start, stop-start);
}
}'
}
### 方法简要说明:
### 从list返回的结果中,找到key=value时的tagKey值
### 查找json字符串'"key":"value"',找到后,以这个位置为结尾
### 查找{最后一次出现的位置lastIndex,再以lastIndex为起始点,查找tagKey,获取tagKey的值
###
### params: json, key, value, tagKey, defaultValue
function getJsonValuesByAwkWithConditions() {
awk -v json="$1" -v key="$2" -v value="$3" -v tagKey="$4" -v defaultValue="$5" 'BEGIN{
foundKeyCount = 0
pos = match(json, "\""key"\"[ \\t]*?:[ \\t]*\""value"\"");
if (pos == 0) {print defaultValue; exit 0;}
str1 = substr(json, 0, pos)
lastIndex = 0
while (match(str1, "{")) {
lastIndex = lastIndex + RSTART
str1 = substr(str1, RSTART + RLENGTH)
}
if (lastIndex == 0) {print defaultValue; exit 0;}
newStr = substr(json, lastIndex)
pos1 = match(newStr, "\""tagKey"\"[ \\t]*?:[ \\t]*");
if (pos1 == 0) {print defaultValue; exit 0;}
++foundKeyCount;
start = 0; stop = 0; layer = 0;
for (i = pos1 + length(tagKey) + 1; i <= length(newStr); ++i) {
lastChar = substr(newStr, i - 1, 1)
currChar = substr(newStr, i, 1)
if (start <= 0) {
if (lastChar == ":") {
start = currChar == " " ? i + 1: i;
if (currChar == "{" || currChar == "[") {
layer = 1;
}
}
} else {
if (currChar == "{" || currChar == "[") {
++layer;
}
if (currChar == "}" || currChar == "]") {
--layer;
}
if ((currChar == "," || currChar == "}" || currChar == "]") && layer <= 0) {
stop = currChar == "," ? i : i + 1 + layer;
break;
}
}
}
if (start <= 0 || stop <= 0 || start > length(newStr) || stop > length(newStr) || start >= stop) {
if (foundKeyCount == 0) {print defaultValue;} exit 0;
} else {
print substr(newStr, start, stop-start);
}
}'
}
# 获取enterprise_project_id environment_id application_id component_id
function initParpare() {
# 获取environment_id
listEnvsResult=`/usr/local/bin/hcloud CAE ListEnvironments --cli-region="$region" --project_id="$project_id"`
environment_id=`getJsonValuesByAwkWithConditions "$listEnvsResult" "name" "$environment_name" "id" "defaultValue"`
environment_id=`echo "$environment_id" | cut -d '"' -f 2`
echo "environment_id: $environment_id"
if [[ "$environment_id" == "defaultValue" ]]; then
echo "list environments and get environment_id error"
echo "$listEnvsResult"
exit 126
fi
# 获取enterprise_project_id
enterprise_project_id=`getJsonValuesByAwk "$listEnvsResult" "enterprise_project_id" "defaultValue"`
enterprise_project_id=`echo "$enterprise_project_id" | cut -d '"' -f 2`
echo "enterprise_project_id: $enterprise_project_id"
if [[ "$enterprise_project_id" == "defaultValue" ]]; then
echo "get enterprise_project_id error"
echo "$listEnvsResult"
exit 126
fi
# 获取application_id
listAppsResult=`/usr/local/bin/hcloud CAE ListApplications --cli-region="$region" --project_id="$project_id" --X-Environment-ID="$environment_id"`
application_id=`getJsonValuesByAwkWithConditions "$listAppsResult" "name" "$application_name" "id" "defaultValue"`
application_id=`echo "$application_id" | cut -d '"' -f 2`
echo "application_id: $application_id"
if [[ "$application_id" == "defaultValue" ]]; then
echo "list applications and get application_id error"
echo "$listAppsResult"
exit 126
fi
# 获取component_id
listComponentsResult=`/usr/local/bin/hcloud CAE ListComponents --cli-region="$region" --project_id="$project_id" --X-Environment-ID="$environment_id" --application_id="$application_id"`
component_id=`getJsonValuesByAwkWithConditions "$listComponentsResult" "name" "$component_name" "id" "defaultValue"`
component_id=`echo "$component_id" | cut -d '"' -f 2`
echo "component_id: $component_id"
if [[ "$component_id" == "defaultValue" ]]; then
echo "list components and get component_id error"
echo "$listComponentsResult"
exit 126
fi
}
# 每隔15秒查询一次job状态,直到job完成
function waitDeployFinish() {
sleep 10s
id="$1"
leni=${#id}
id=${id:1:leni-2}
echo "job_id= $id"
job_status=""
while [[ "$job_status" != "success" ]]; do
job_status_result=`/usr/local/bin/hcloud CAE ShowJob --cli-region="$region" --project_id="$project_id" --job_id="$id" --X-Environment-ID="$environment_id"`
job_status=`getJsonValuesByAwk "$job_status_result" "status" "defaultValue"`
if [[ "$job_status" == "defaultValue" ]]; then
echo "ShowJob failed"
echo "$job_status_result"
return
fi
job_status=`echo "$job_status" | cut -d '"' -f 2`
if [[ "$job_status" != "running" && "$job_status" != "success" ]]; then
echo 'upgrade failed'
echo "$job_status_result"
return
fi
sleep 15s
done
echo 'upgrade success'
}
function deploy() {
if [[ "$deploy_type" == "software" ]]; then
obs_software_upgrade
elif [[ "$deploy_type" == "image" ]]; then
swr_image_upgrade
else
return
fi
# 打印升级组件的结果
echo "upgrade result: $action_result"
# 获取结果中的job_id
job_id=`getJsonValuesByAwk "$action_result" "job_id" "defaultValue"`
if [[ "$job_id" == "defaultValue" ]]; then
echo "upgrade failed"
exit 126
fi
# 等待升级完成
waitDeployFinish "$job_id"
}
function main() {
initParpare
upgradeComponentVersion
deploy
}
main
脚本参数说明
|
参数 |
是否必须 |
参数类型 |
描述 |
|---|---|---|---|
|
region |
是 |
String |
项目名称。 |
|
project_id |
是 |
String |
项目id。 |
|
environment_name |
是 |
String |
组件的环境名称。 |
|
application_name |
是 |
String |
组件的应用名称。 |
|
component_name |
是 |
String |
组件名称。 |
|
deploy_type |
是 |
String |
部署类型: software或image。
|
|
obsutil |
否 |
String |
当使用软件包部署如jar包部署时为必须参数。上传jar包到obs的工具安装的绝对路径。 示例:/root/tools/obsutil/obsutil_linux_amd64_5.4.6/obsutil。 |
|
bucket_name |
否 |
String |
当使用软件包部署时为必须参数。存放软件包的obs桶名称。 |
|
bucket_dir |
否 |
String |
当使用软件包部署时为必须参数。 软件包在obs桶中的存放目录,默认是根目录,目录需要以/结尾,如果obs桶中没有这个目录,会自动创建出该目录。如根目录“/”,根目录下面的test目录“/test/”。 |
|
swr_organization |
否 |
String |
当使用镜像部署时为必须参数。上传到swr的组织名称。 |
|
AK |
否 |
String |
当使用镜像部署时为必须参数。创建永久AK、SK中的AK参数,用于登录swr镜像仓库。 |
|
login_secret |
否 |
String |
当使用镜像部署时为必须参数。swr的登录密钥,用于登录swr镜像仓库。通过创建永久AK、SK获取的AK/SK,执行如下命令,返回的结果就是登录密钥: printf "$AK" | openssl dgst -binary -sha256 -hmac "$SK" | od -An -vtx1 | sed 's/[ \n]//g' | sed 'N;s/\n//' |
参数值获取
- 获取region、project_id值:
- 获取组件所在的环境名称environment_name,应用名称application_name和组件名称component_name:
登录CAE控制台,单击“组件列表”,找到目标组件,例如image组件,如图3所示。


