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 "外部传入参数数量不为1,参考配置流水线构建任务中的流水线脚本参数build_target_name" 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_detials=`/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_detials" "version" "defaultValue"` version=`echo "$version" | cut -d '"' -f 2` echo "current version: $version" if [[ "$version" == "defaultValue" ]]; then echo "get component detials and get component version error" echo "$component_detials" 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所示。