1 Jenkins Job Builder简介
顾名思义,Jenkins Job Builder(以下简称“JJB”)就是用来创建Jenkins任务的工具。为了简化配置大量Jenkins任务的工作量,Openstack采用更容易阅读的基于yaml或json格式的文件来编辑任务,然后使用JJB将yaml或json格式的配置转化为可以被Jenkins理解的XML格式的任务配置文件,并更新到Jenkins中。
工作原理很简单,Jenkins创建的任务实际是以XML文件的格式保存在$JENKINS_HOME/jobs/[job-name]/config.xml的,JJB能够将YAML转化为XML文件(借助Jenkins提供的命令接口),并更新到Jenkins中。如下图所示:
具体来说,JJB同Jenkins的“交流”是通过Jenkins API(默认通过配置文件/etc/jenkins_jobs/jenkins_jobs.ini定义Jenkins服务端),从而创建和修改任务都不需要restart或reload Jenkins服务。并且Jenkins会检查JJB提供的XML文件,如果检查不通过那么JJB的执行会返回错误。
使用JJB的优点也是显而易见的:
- 无需通过前台页面来进行任务创建,方便puppet、docker等进行服务器配置管理或容器的构建;
- YAML文件作为配置可以通过版本管理工具管理起来;
- 可以通过定义job-template或参数,简化任务配置,有效减少工作量。
2 Jenkins Job Builder使用方法
简单介绍一下测试配置、更新任务以及删除任务的方法,也很简单,只需要一个“jenkins-jobs”命令即可。
2.1 测试配置
当任务配置的yaml文件编写完成之后,可以通过“jenkins-jobs test”测试配置格式和内容是否正确。
jenkins-jobs test path/to/myjob.yaml
若测试通过,将输出XML格式的任务配置,如果想将测试的XML格式的任务配置输出到文件,可以添加“-o”参数:
jenkins-jobs test -o output path/to/myjob.yaml
2.2 更新任务
测试通过后,可以使用“jenkins-jobs update”命令将yaml文件定义的任务更新到jenkins中。
jenkins-jobs [--conf jenkins_jobs.ini] update path/to/job1.yaml
update命令需要指定保存有Jenkins服务器信息的配置文件,用“–conf”来显示指定该配置文件,如果不显示指定,则默认读取“/etc/jenkins_jobs/jenkins_jobs.ini”文件。该配置文件保存有jenkins的url和登录信息,内容如下:
[jenkins]
user=jenkins
password=password
url=http://localhost:8081/jenkins
从而JJB可以将任务更新到ini配置文件指定的Jenkins。
路径也可以是目录,那么就是更新指定目录下所有的yaml,yml和json文件。多个路径用冒号隔开。
2.3 删除任务
删除任务使用如下命令。
jenkins-jobs [--conf jenkins_jobs.ini] delete job1
3 配置文件的编写
可以被JJB识别的Job配置文件包括yaml和json两种格式,以下以yaml文件为例。
本节内容为了给下一节做铺垫,因此不详细展开,具体请参考JJB文档。
3.1 Job的编写
任务定义部分以“- job:”标识的内容,就不展开说了,如:
- job:
name: job-name
project-type: freestyle
defaults: global
description: 'Do not edit this job through the web!'
disabled: false
display-name: 'Fancy job name'
concurrent: true
3.2 Job Template的编写
如果多个任务都是类似的配置,那么可以使用任务模板来定义,然后在“project”中将模板任务实现。
任务模板的语法及参数与任务定义相同,并且可以在任意地方根据需要增加变量。变量通过两个大括号定义,如{name}(在字符串中,变量最好用引号包起来;如果确实需要表示“{”和“}”字符,用“{{”和“}}”表示)。
任务模板定义部分以“- job-template:”标识,通常必须包含一个{name}变量,否则所有的任务实例都采用同样的名字,如:
- job-template:
name: '{name}-unit-tests'
publishers:
- email:
recipients: '{mail-to}'
- job-template:
name: '{name}-perf-tests'
publishers:
- email:
recipients: '{mail-to}'
3.3 Project的编写
项目用于将所有相关的任务归类(在实际使用时可以按照开发的project来分),以及给任务模板提供变量值,所以project的属性并无限制,可以定义任何模板中需要的属性。
- project:
name: project-name
jobs:
- '{name}-unit-tests':
mail-to: developer@nowhere.net
- '{name}-perf-tests':
mail-to: projmanager@nowhere.net
如果变量的值是一个list,那么会基于list的每个元素进行实现。多个list会导致出现“笛卡尔积”个具体实现。比如:
- job-template:
name: '{name}-{branch}'
builders:
- shell: 'git checkout {branch_name}'
- project:
name: project-name
branch:
- a:
branch_name: feature-a
- b:
branch_name: feature-b
jobs:
- '{name}-{branch}'
3.4 Job Group的编写
任务组其实就是用于归纳整理,具体看配置文件一目了然:
- job-template:
name: '{name}-unit-tests'
builders:
- shell: unittest
publishers:
- email:
recipients: '{mail-to}'
- job-template:
name: '{name}-perf-tests'
builders:
- shell: perftest
publishers:
- email:
recipients: '{mail-to}'
- job-group:
name: '{name}-tests'
jobs:
- '{name}-unit-tests':
mail-to: developer@nowhere.net
- '{name}-perf-tests':
mail-to: projmanager@nowhere.net
- project:
name: project-name
jobs:
- '{name}-tests'
3.5 Macro的编写
宏的用处都不陌生,不少语言里都有宏,一次定义,多次使用。好处自然是避免同样的代码出现多多个地方,修改的时候只需要改宏定义就行了。
在任务定义过程中,动作类的属性,比如builders或publishers,都可以定义为宏。简单看个builders的例子。下面的任务会在构建时执行“make test”命令:
- job:
name: foo-test
builders:
- shell: 'make test'
- builder:
name: make-test
builders:
- shell: 'make test'
- job:
name: a-test
builders:
- make-test
- job:
name: b-test
builders:
- make-test
宏也可以采用参数的方式来减少代码量:
# 定义一个名为“add”的宏,并将“number”作为参数,这个宏实现echo打印功能
- builder:
name: add
builders:
-shell: 'echo Adding {number}'
# 定义一个具体的基于“add”的宏“add-one”,变量“number”设置为“one”
- builder:
name: add-one
builders:
-add
number: “one”
# 在任务中实现宏
- job:
name: test-macro
builders:
# 基于具体的宏“add-one”
-add-one
# 基于宏“add”
-add
number: “two”
# 错误!对于含变量的宏如果不给出变量值将会导致错误的输出
-add
<builders>
<hudson.tasks.Shell>
<command>echo Adding one</command>
</hudson.tasks.Shell>
<hudson.tasks.Shell>
<command>echo Adding two</command>
</hudson.tasks.Shell>
<hudson.tasks.Shell>
<command>echo Adding {number}</command>
</hudson.tasks.Shell>
</builders>
3.6 Defaults的编写
许多共性的属性或动作可以提取出来放到一个默认集合中,供其他的任务使用。
如果Defaults的名字是“global”,那么将默认被所有的任务和任务模板使用。当然在任务中也可以显式定义属性值来覆盖全局默认的属性值。
举个例子:
- defaults:
name: global
arch: 'i386'
- job-template:
name: 'build-{arch}'
builders:
- shell: "echo Build arch {arch}."
- project:
name: project-name
jobs:
- 'build-{arch}'
- 'build-{arch}':
arch: 'amd64'
4 Openstack如何使用JJB
在Openstack环境中,yaml脚本文件可以在project-config: jenkins/jobs/目录下找到,在该目录下有4种配置文件:
- defaults.yaml,全局默认配置在这个文件中;
- macros.yaml,所有的宏保存在这个文件中;
- <project-name>.yaml,各个项目的配置脚本;
- projects.yaml,一个文件包含所有项目的jobs的配置。
4.1 Defaults
default.yaml中是所有Jenkins任务的全局属性定义,即name为“global”的属性,比如默认的描述,任务是并行执行的,任务超期时间为30分钟等。
4.2 Macros
所有的宏定义在macro.yaml文件中,包括一些比较通用的builders或publishers,供各任务调用,如:
- builder:
name: git-prep
builders:
- shell: "/slave_scripts/git-prep.sh"
- builder:
name: docs
builders:
- shell: "/slave_scripts/run-docs.sh"
- publisher:
name: console-log
publishers:
- scp:
site: 'scp-server'
files:
- target: 'logs/$JOB_NAME/$BUILD_NUMBER'
copy-console: true
copy-after-failure: true
4.3 任务和任务模板
任务和任务模板定义在各个项目的脚本文件中。每个项目都有一个以项目名命名的<project-name>.yaml文件,里边的内容基本就是“- job:”和“- job-template:”,还有“- job-groups:”。
4.4 项目配置
所有的项目是集中配置在projects.yaml文件中的,各个项目以字母顺序排序,各项目的job属性来自任务和任务模板的定义。