WYDevOps敏捷工具的架构设计(三)——三级扩展机制

        前一篇文章《WYDevOps敏捷工具的架构设计(二)——部署图、参数配置及其扩展机制》我们介绍了整个工具集与Jenkins集成的系统部署图,给出了Jenkins流水线的样例代码,并介绍了入口脚本wydevops.sh主要的全局参数(命令行参数),最后着重说明了自定义全局参数的扩展机制。本篇文章主要介绍wyDevOps脚本中使用的扩展机制。

       首先,在公司层面需要有统一的微服务发布规范。

       对于SpringCloud技术栈的微服务而言,可能需要统一定义注册和配置中心;可能需要统一定义不同环境(dev、test、pre、prod)下数据库的连接配置参数、部署服务的集群IP地址;可能需要统一定义微服务生成docker镜像的一些默认规则,例如:时区、挂载路径、网络、镜像仓库地址、镜像推送流程等等。

       对于Springboot + K8S技术栈的微服务而言,还可能需要统一定义网关路由规范、默认的ConfigMap、探活和就绪配置、CPU和内存资源配置、卷挂载配置等等。

        其次,对于同时存在多种开发语言的公司,还需要在统一的标准的DevOps流程中能为不同语言提供扩展机制。例如:显而易见的,不同语言的项目,其编译过程各不相同,这需要针对编译过程提供扩展点。

        最后,不同的项目,也可能会有功能点扩展需要。例如:某个Java项目其application.yml配置文件中有一个testPort参数需要在安装时指定,在application.yml文件中其值定义为{{ .Values.testPort }}, 在使用helm进行服务安装打包时,在chart镜像的values.yaml文件中就需要存在testPort参数。此时该项目就需要扩展流程中values.yaml文件参数定义标准方法。

        综上所述,我们定义的标准DevOps(编译构建、docker镜像生成和推送、chart镜像生成和推送、服务部署)流程中的每一个扩展点都需要能同时具备公司层面、语言级层面、项目级层面的扩展能力。下面给出扩展点的调用方式和三级扩展机制的实现,很简单的。

1.  在流程中扩展点的调用方式举例如下:

invokeExtendPointFunc "initGlobalParams" "全局参数初始化功能扩展点"

其中:

invokeExtendPointFunc——标准的扩展点调用方法。

initGlobalParams——扩展点的名称。

全局参数初始化功能扩展点——扩展点的说明信息,用于内部日志输出

2. invokeExtendPointFunc方法的实现

#功能扩展点标准调用方法
function invokeExtendPointFunc() {
  local l_funcName=$1
  local l_extentPointName=$2

  local l_funcName1
  local l_param=("${@}")

  #删除前两个参数
  # shellcheck disable=SC2184
  unset l_param[0]
  # shellcheck disable=SC2184
  unset l_param[1]
  # shellcheck disable=SC2206
  l_param=(${l_param[*]})

  #调用公共功能扩展
  extendLog "\n--->> ${l_extentPointName}(${l_funcName}) <<---"

  if type -t "${l_funcName}_ex" > /dev/null; then
    info "调用公共功能扩展点:${l_funcName}_ex..."
    # shellcheck disable=SC2068
    "${l_funcName}_ex" ${l_param[@]}
  else
    info "未检测到公共功能扩展点:${l_funcName}_ex..."
  fi

  #调用语言级功能扩展
  l_funcName1="_${l_funcName}_ex"
  if type -t "${l_funcName1}" > /dev/null; then
    info "调用${gLanguage}语言级功能扩展点:${l_funcName1}..."
    # shellcheck disable=SC2068
    "${l_funcName1}" ${l_param[@]}
  else
    info "未检测到${gLanguage}语言级功能扩展点:${l_funcName1}..."
  fi

  #如果存在项目级扩展,则调用之
  # shellcheck disable=SC2068
  executeShellScript "${gBuildPath}" "${l_funcName}.sh" ${l_param[@]}

  extendLog "<<--- ${l_extentPointName}(${l_funcName}) --->>\n"

  unset l_funcName
  unset l_funcName1
  unset l_extentPointName
  unset l_param
}

从上面的代码中可以看到,代码依次执行了公共级(公司级)、语言级、项目级三级扩展函数。

以第1点调用语句为例:

公共级扩展函数的名称是:initGlobalParams_ex (initGlobalParams是动态传入的)

语言级扩展函数的名称是:_initGlobalParams_ex (initGlobalParams是动态传入的)

项目级扩展文件(不能是函数了)的名称是:initGlobalParams.sh (initGlobalParams是动态传入的)

executeShellScript方法的实现如下:

function executeShellScript() {
   local l_buildPath=$1
   local l_scriptFile=$2
   local l_localScriptFile

   export gShellExecuteResult

   #如果l_scriptFile脚本存在,则调用之
   l_localScriptFile="${l_buildPath}/ci-cd/${l_scriptFile}"
   if [ -f "${l_localScriptFile}" ];then
     # shellcheck disable=SC1090
     source "${l_localScriptFile}" "${@}"
     gShellExecuteResult="true"
     info "调用项目级功能扩展${l_scriptFile}...成功"
   else
     gShellExecuteResult="false"
     info "未发现项目级功能扩展文件:${l_scriptFile}"
   fi

   unset l_buildPath
   unset l_scriptFile
   unset l_localScriptFile
}

       从上述代码可知,脚本会检查在当前项目主模块目录(gBuildPath)中ci-cd子目录下是否存在指定的sh脚本文件,如果存在则通过source方式加载并执行之。

       通过invokeExtendPointFunc函数,我们可以看到在执行扩展方法前先判断了目标函数是否存在,如果存在则调用之。这一点是如何实现的呢?怎样才能保证正确的扩展方法能被加载和调用呢?

先介绍一下wydevops源码的项目结构,如下图:

 

如上图,项目入口脚本是wydevops.sh文件,文件内容如下:

#!/usr/bin/env bash

#1.进入获取脚本所在的目录。
# shellcheck disable=SC2164
_selfRootDir=$(cd "$(dirname "$0")"; pwd)

#2.导入yaml函数库文件、向外发送通知的库文件。
source "${_selfRootDir}/yaml-helper.sh"
source "${_selfRootDir}/notify-helper.sh"
#3.引入全局变量及其默认值定义文件。
source "${_selfRootDir}/global-params.sh"

partLog "第一部分 初始化全局参数"

info "解析命令选项和传入参数"
parseOptions "${@}"

if [ ! "${gBuildScriptRootDir}" ];then
  #读取Jenkins环境变量BUILD_SCRIPT_ROOT。
  gBuildScriptRootDir="${BUILD_SCRIPT_ROOT}"
fi
info "gBuildScriptRootDir参数初始化:${gBuildScriptRootDir}"

#流水线脚本所在的目录名称
gPipelineScriptsDir="${gBuildScriptRootDir}/pipeline-stages"
info "gPipelineScriptsDir参数初始化:${gPipelineScriptsDir}"

info "加载功能扩展库文件:wydevops-extend-point.sh"
source "${gPipelineScriptsDir}/common/wydevops-extend-point.sh"

#全局参数初始化前扩展点:检查必须设置的全局参数。
invokeExtendPointFunc "onBeforeInitGlobalParams" "全局参数初始化前扩展点"

invokeExtendPointFunc "initGlobalParams" "全局参数初始化功能扩展点"

invokeExtendPointFunc "onAfterInitGlobalParams" "全局参数初始化后扩展点"

info "执行CI/CD标准流程..."
source "${_selfRootDir}/cicd-entry.sh"

说明如下:

1. parseOptions方法解析了命令行输入的所有参数。其中包含了项目语言类型参数gLanguage。

2. 解析完命令行参数后,再加载功能扩展库文件wydevops-extend-point.sh。

    功能扩展库文件的名称标准格式为{主脚本名称}-extend-point.sh。上图中可以看到项目中common目录(公共扩展文件目录)还有编译构建脚本build.sh的功能扩展文件build-extend-point.sh、docker镜像生成和推送脚本docker.sh的功能扩展文件docker-extend-point.sh、chart镜像生成和推送脚本chart.sh的功能扩展文件chart-extend-point.sh、服务部署脚本deploy.sh的功能扩展文件deploy-extend-point.sh。

    上图中与build.sh文件同级的存在多个语言名称命名的目录,这些目录下存放的是该类语言的功能扩展文件,名称是与公共功能扩展文件名称一一对应的。上图展开了java语言目录,可以看到同样存在各个阶段的功能扩展文件。

3. 这些扩展文件是如何加载的呢?用下面wydevops-extend-point.sh的加载过程为例:

source "${gPipelineScriptsDir}/common/wydevops-extend-point.sh"

       首先各个阶段(wydevops.sh、build.sh、docker.sh、chart.sh、deploy.sh)脚本都会到common目录下加载自己的公共功能扩展文件。

        在公共功能扩展文件中会自动加载对应的语言级功能扩展文件。以wydevops-extend-point.sh为例,如下图:

        图中第7行可以看到,wydevops-extend-point.sh脚本会先检查是否存在当前语言类型的同名脚本,如果存在则加载之。这样就确保了invokeExtendPointFunc函数中能正确动态检查和调用公共级扩展和语言级扩展函数。项目级扩展采用的是sh脚本方式扩展的,如果存在则直接加载执行即可。
        wyDevOps的三级扩展机制就介绍到这里了。敬请期待下一篇《WYDevOps敏捷工具——Docker镜像的生成和管理》

另:本系列文章写完后,我将开源wyDevOps项目,目前还在整理中。期待您的点赞和关注。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值