Jenkins的Api

术语定义

名词 说明
job 任务
payload 在POST请求中提交的数据
{optionalFolderPath} 可选参数:任务所在目录的路径
{job_name} 必须参数:任务名称
  • 在 GET/POST 时需要附加 HTTP 认证才能访问 API
  • 本文使用的数据结构可以在 jenkins-rest/domain 中查看详细定义

API类型

API类型 说明
JobsAP 任务管理(任务信息、创建、修改)
OBPluginManagerAPI 插件管理(插件信息、安装插件)
QueueAPI 任务队列相关(队列状态)
StatisticsAPI Jenkins统计信息
CrumbIssuerAPI 系统哈希值信息(用于防御CSRF攻击)
SystemAPI Jenkins系统状态(版本、路径)

API汇总

名称 API
创建 Job POST http://localhost:8080/createItem/api/json
更新 Job POST http://localhost:8080/job/{job_name}/config.xml/api/json
获取 Job GET http://localhost:8080/job/{job_name}/api/json
获取 JobXml GET http://localhost:8080/job/{job_name}/config.xml/api/json
删除 Job POST http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/doDelete
enable Job POST http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/enable
disable Job POST http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/disable
获取任务描述 GET http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/description
设置任务描述 POST http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/description
创建 Build POST http://localhost:8080/job/{job_name}/build/api/json
获取 QueueItem GET http://localhost:8080/queue/item/17/api/json
取消任务队列 POST http://127.0.0.1:8080/cancelItem?id={id}
所有任务队列信息 GET http://127.0.0.1:8080/queue/api/json
获取 Build信息 GET http://localhost:8080/job/test/6/api/json
获取上次构建序号 GET http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/lastBuild/buildNumber
获取上次构建时间戳 GET http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/lastBuild/buildTimestamp
获取TXT日志 GET http://localhost:8080/job/test/{build_number}/logText/progressiveText/api/json
获取 Html 日志 GET http://localhost:8080/job/test/{build_number}/logText/progressiveHtml/api/json
系统哈希值信息 GET http://127.0.0.1:8080/crumbIssuer/api/xml?{key}={value}
load统计信息 GET http://127.0.0.1:8080/overallLoad/api/json
插件管理 GET http://127.0.0.1:8080/pluginManager/api/json
安装插件 POST http://127.0.0.1:8080/pluginManager/installNecessaryPlugins

API详述

创建 Job

jenkins 的配置都是靠 xml 的格式落地的,所以配置其实都是 xml 的形式.

1
POST http://127.0.0.1:8080/createItem

参数

key value
name 任务名称
payload XML配置文件

返回类型:RequestStatus

字段 类型 说明
value Boolean
errors List

如何知道 config.xml应该如何编写呢?

  • 可以在 jenkins 收工创建一个需要的项目,然后编辑完成后,到 jenkins 工作目录下 找到 jobs/{job_name}/config.xml 用他作为模板来书写你需要的模板.
  • 通过获取 xml 的 api 来获取

GET http://localhost:8080/job/{job_name}/config.xml/api/json

Java Client

1
2
jenkinsServer.createJob("auto_test_job", replacedText, true);
String xml = jenkinsServer.getJobXml("auto_test_job");

更新Job

1
POST http://localhost:8080/job/{job_name}/config.xml/api/json

参数

字段 说明
payload XML配置文件

config.xml的内容传入到 body 中,contentType 设置为text/xml

返回类型:Boolean

Java Client

1
jenkinsServer.updateJob("auto_test_job", replacedText, true);

job-info 获取任务信息

GET http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/api/json

返回类型:JobInfo

字段 类型 说明
description String 描述
name String 项目名称
url boolean 路径
buildable String 是否可构建
builds List 构建记录
lastBuild BuildInfo 上次构建记录
……

delete 删除任务

1
POST http://127.0.0.1:8080/{optionalFolderPath}job/{project_name}/doDelete

返回类型:RequestStatus

补充:

也可以使用

1
DELETE https://<Jenkins_url>/job/<job_name>/

注意最后有个 /,不加 / 不能正常删除

enable允许任务

1
POST http://127.0.0.1:8080/{optionalFolderPath}job/{project_name}/enable

返回类型:Boolean

disable 禁止任务

1
POST http://127.0.0.1:8080/{optionalFolderPath}job/{project_name}/disable

返回类型:Boolean

get-description 获取任务描述

1
GET http://127.0.0.1:8080/{optionalFolderPath}job/{project_name}/description

返回类型:String

set-description 设置任务描述

1
POST http://127.0.0.1:8080/{optionalFolderPath}job/{project_name}/description

参数

key value
description 描述

返回类型:Boolean

创建 Build

1
2
POST http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/build
POST http://localhost:8080/job/{job_name}/build/api/json

返回类型: IntegerResponse

字段 类型 说明
value Integer
errors List

build-with-params 使用参数创建任务

1
POST http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/buildWithParameters

参数

key value
payload Map<String, List> properties

返回类型: IntegerResponse

新的构建请求提交到服务器成功后返回一个类似于队列ID的东西,因为是异步构建,那么要获取构建的状态,就需要,用这个队列 id去进一步的获取. 例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ curl -v  -XPOST http://localhost:8080/job/test/build/api/json
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /job/test/build/api/json HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 201 Created
< Date: Sat, 05 Jan 2019 08:33:45 GMT
< X-Content-Type-Options: nosniff
< Location: http://localhost:8080/queue/item/17/
< Content-Length: 0
< Server: Jetty(9.4.z-SNAPSHOT)
<
* Connection #0 to host localhost left intact

上面的Location: http://localhost:8080/queue/item/17/就是返回的队列信息,下面的 queueItem 获取就是依赖这个.

根据 QueueId 获取 QueueItem

1
GET http://localhost:8080/queue/item/17/api/json 

参数

字段 说明
{queueId} 任务队列ID

返回类型:QueueItem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$ curl  http://localhost:8080/queue/item/17/api/json\?pretty\=true
{
"_class" : "hudson.model.Queue$LeftItem",
"actions" : [
{
"_class" : "hudson.model.CauseAction",
"causes" : [
{
"_class" : "hudson.model.Cause$UserIdCause",
"shortDescription" : "由用户 anonymous 启动",
"userId" : null,
"userName" : "anonymous"
}
]
}
],
"blocked" : false,
"buildable" : false,
"id" : 17,
"inQueueSince" : 1546677225670,
"params" : "",
"stuck" : false,
"task" : {
"_class" : "hudson.maven.MavenModuleSet",
"name" : "test",
"url" : "http://localhost:8080/job/test/",
"color" : "blue"
},
"url" : "queue/item/17/",
"why" : null,
"cancelled" : false,
"executable" : {
"_class" : "hudson.maven.MavenModuleSetBuild",
"number" : 6,
"url" : "http://localhost:8080/job/test/6/"
}
}

cancel 取消任务队列

1
POST http://127.0.0.1:8080/cancelItem?id={id}

参数

字段 说明
{id} 任务队列ID

返回类型:RequestStatus

queue 所有任务队列信息

1
GET http://127.0.0.1:8080/queue/api/json

返回类型:List

字段 类型 说明
blocked Boolean 是否阻塞
buildable Boolean 是否可构建
id Integer
inQueueSince Long
params Map<String, String> 任务参数
task Task Task中包含任务名称和URL
……

获取 Build 详情

1
GET http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/{number}/api/json

返回类型:BuildInfo

字段 类型 说明
artifacts List artifacts
actions Lis actions
building boolean 路径
description String 描述
……
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
curl http://localhost:8080/job/test/6/api/json\?pretty\=true
{
...
"building" : false,
"description" : null,
"displayName" : "#6",
"duration" : 13631,
"estimatedDuration" : 17999,
"executor" : null,
"fullDisplayName" : "test #6",
"id" : "6",
"keepLog" : false,
"number" : 6,
"queueId" : 17,
"result" : "SUCCESS",
"timestamp" : 1546677234794,
"url" : "http://localhost:8080/job/test/6/",
"builtOn" : "",
...
}

从返回结果可以看到 是否还在 build:"building" : false,如果 build 结束状态就在:"result" : "SUCCESS"

获取上次Build详情

1
curl http://172.12.12.234:8080/job/pytest_7.0/lastBuild/api/xml --user jenkins:1

last-build-number 获取上次构建序号

1
GET http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/lastBuild/buildNumber

返回类型:Integer

last-build-timestamp 获取上次构建时间戳

1
GET http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/lastBuild/buildTimestamp

返回类型:String

progressive-text 获取构建控制台输出

获取上次构建的日志

1
GET http://127.0.0.1:8080/{optionalFolderPath}job/{job_name}/lastBuild/logText/progressiveText

返回类型:ProgressiveText

字段 类型 说明
text String 控制台输出
size Integer 字数
hasMoreData Boolean 是否有更多数据

获取某次构建的日志

1
2
3
4
5
// text
GET http://localhost:8080/job/test/{build_number}/logText/progressiveText/api/json

// html
GET http://localhost:8080/job/test/{build_number}/logText/progressiveHtml/api/json
1
2
3
4
5
6
7
8
9
10
11
12
JobWithDetails job = jenkinsServer.getJob(jenkinsJob);
...
QueueReference reference = job.build( true);
...
QueueItem queueItem = jenkinsServer.getQueueItem(new QueueReference(queuePart));
...
Build build = jenkinsServer.getBuild(queueItem);
...
BuildWithDetails details = build.details();
BuildResult result = details.getResult();
...
String logs = details.getConsoleOutputText();

CrumbIssuer 系统哈希值信息(用于防御CSRF攻击)

  • CrumbIssuerApi
  • path: /crumbIssuer/api/xml

crumb

1
GET http://127.0.0.1:8080/crumbIssuer/api/xml?{key}={value}

参数

key value
xpath concat(//crumbRequestField,”:”,//crumb)

返回类型:Crumb

字段 类型
value String
errors List

Statistics 统计信息

  • StatisticsApi
  • path: /

overall-load

1
GET http://127.0.0.1:8080/overallLoad/api/json

返回类型:OverallLoad

字段 类型 说明
availableExecutors Map<String, String>
busyExecutors Map<String, String>
connectingExecutors Map<String, String>
definedExecutors Map<String, String>
idleExecutors Map<String, String>
onlineExecutors Map<String, String>
queueLength Map<String, String>
totalExecutors Map<String, String>
totalQueueLength Map<String, String>

System 系统信息

  • path: /

返回类型:SystemInfo

字段 类型 说明
hudsonVersion String
jenkinsVersion String
jenkinsSession String
instanceIdentity String
sshEndpoint String
server String

PluginManager 插件管理(插件信息、安装插件)

  • PluginManagerApi
  • path: /pluginManager

plugins 插件列表

1
GET http://127.0.0.1:8080/pluginManager/api/json

返回类型:List

字段 类型 说明
active Boolean
backupVersion String
bundled Boolean
deleted Boolean
downgradable Boolean
enabled Boolean
longName String
……

installNecessaryPlugins 安装插件

1
POST http://127.0.0.1:8080/pluginManager/installNecessaryPlugins

参数

1
payload: <jenkins><install plugin="{pluginID}"/></jenkins>
字段 说明
{pluginID} 要安装的插件ID

返回类型:RequestStatus

代码示例

配置

导入依赖

1
2
3
4
5
6
<!--jenkins-java-client-->
<dependency>
<groupId>com.offbytwo.jenkins</groupId>
<artifactId>jenkins-client</artifactId>
<version>0.3.8</version>
</dependency>

创建连接配置,配置对应的信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import com.offbytwo.jenkins.JenkinsServer;
import com.offbytwo.jenkins.client.JenkinsHttpClient;

import java.net.URI;
import java.net.URISyntaxException;

public class JenkinsConnect {

private JenkinsConnect(){}

// 连接 Jenkins 需要设置的信息
static final String JENKINS_URL = "http://jenkins:8080/";
static final String JENKINS_USERNAME = "jenkins";
static final String JENKINS_PASSWORD = "jenkins";

/**
* Http 客户端工具
*
* 如果有些 API 该Jar工具包未提供,可以用此Http客户端操作远程接口,执行命令
* @return
*/
public static JenkinsHttpClient getClient(){
JenkinsHttpClient jenkinsHttpClient = null;
try {
jenkinsHttpClient = new JenkinsHttpClient(new URI(JENKINS_URL), JENKINS_USERNAME, JENKINS_PASSWORD);
} catch (URISyntaxException e) {
e.printStackTrace();
}
return jenkinsHttpClient;
}

/**
* 连接 Jenkins
*/
public static JenkinsServer connection() {
JenkinsServer jenkinsServer = null;
try {
jenkinsServer = new JenkinsServer(new URI(JENKINS_URL), JENKINS_USERNAME, JENKINS_PASSWORD);
} catch (URISyntaxException e) {
e.printStackTrace();
}
return jenkinsServer;
}
}

JENKINS_URL是Jenkins的反向代理地址, Configure System -> Jenkins location url, 一般和Jenkins首页访问地址一致

JENKINS_USERNAME Jenkins登录账号

JENKINS_PASSWORD Jenkins账号密码

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
import com.offbytwo.jenkins.JenkinsServer;
import com.offbytwo.jenkins.client.JenkinsHttpClient;
import com.offbytwo.jenkins.model.Build;
import com.offbytwo.jenkins.model.Job;
import com.offbytwo.jenkins.model.JobWithDetails;
import com.offbytwo.jenkins.model.MavenJobWithDetails;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class JobApi {

// Jenkins 对象
private JenkinsServer jenkinsServer;
// http 客户端对象
private JenkinsHttpClient jenkinsHttpClient;

/**
* 构造方法中调用连接 Jenkins 方法
*/
JobApi() {
// 连接 Jenkins
jenkinsServer = JenkinsConnect.connection();
// 设置客户端连接 Jenkins
jenkinsHttpClient = JenkinsConnect.getClient();
}

/**
* 创建 Job
*/
public void ceateJob(){
try {
/**创建一个流水线任务,且设置一个简单的脚本**/
// 创建 Pipeline 脚本
String script = "node(){ \n" +
"echo 'hello world!' \n" +
"}";
// xml配置文件,且将脚本加入到配置中
String xml = "<flow-definition plugin=\"workflow-job@2.32\">\n" +
"<description>测试项目</description>\n" +
"<definition class=\"org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition\" plugin=\"workflow-cps@2.66\">\n" +
"<script>" + script + "</script>\n" +
"<sandbox>true</sandbox>\n" +
"</definition>\n" +
"</flow-definition>";
// 创建 Job
jenkinsServer.createJob("test-job",xml, true);
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 更新 Job
*
* 更改之前创建的无参数Job,更改其为参数Job
*/
public void updateJob(){
try {
/**
* 更改一个流水线任务,让一个无参数的任务变成带参数任务
*/
// 创建 Pipeline 脚本,用一个key变量
String script = "node(){ \n" +
"echo \"${key}\" \n" +
"}";
// xml配置文件,且将脚本加入到配置中
String xml = "<flow-definition plugin=\"workflow-job@2.32\">\n" +
"<actions/>\n" +
"<description>测试项目</description>\n" +
"<keepDependencies>false</keepDependencies>\n" +
"<properties>\n" +
"<hudson.model.ParametersDefinitionProperty>\n" +
"<parameterDefinitions>\n" +
"<hudson.model.StringParameterDefinition>\n" +
"<name>key</name>\n" +
"<description>用于测试的字符变量</description>\n" +
"<defaultValue>hello</defaultValue>\n" +
"<trim>false</trim>\n" +
"</hudson.model.StringParameterDefinition>\n" +
"</parameterDefinitions>\n" +
"</hudson.model.ParametersDefinitionProperty>\n" +
"</properties>\n" +
"<definition class=\"org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition\" plugin=\"workflow-cps@2.66\">\n" +
"<script>" + script + "</script>\n" +
"<sandbox>true</sandbox>\n" +
"</definition>\n" +
"<disabled>false</disabled>\n" +
"</flow-definition>";
// 创建 Job
jenkinsServer.updateJob("test-job",xml, true);
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 获取 Job 基本信息
*/
public void getJob(){
try {
// 获取 Job 信息
JobWithDetails job = jenkinsServer.getJob("das-app-android-pkg");
// 获取 Job 名称
System.out.println(job.getName());
// 获取 Job URL
System.out.println(job.getUrl());
// 获取 Job 下一个 build 编号
System.out.println(job.getNextBuildNumber());
// 获取 Job 显示的名称
System.out.println(job.getDisplayName());
// 输出 Job 描述信息
System.out.println(job.getDescription());
// 获取 Job 下游任务列表
System.out.println(job.getDownstreamProjects());
// 获取 Job 上游任务列表
System.out.println(job.getUpstreamProjects());
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 获取 Maven Job 信息
*/
public void getMavenJob(){
try {
// 获取 Job 信息
MavenJobWithDetails job = jenkinsServer.getMavenJob("test-job");
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 获取 Job 列表
*/
public void getJobList(){
try {
// 获取 Job 列表
Map<String, Job> jobs = jenkinsServer.getJobs();
for (Job job:jobs.values()){
System.out.println(job.getName());
}
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 获取 View 名称获取 Job 列表
*/
public void getJobListByView(){
try {
// 获取 Job 列表
Map<String,Job> jobs = jenkinsServer.getJobs("all");
for (Job job:jobs.values()){
System.out.println(job.getName());
}
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 查看 Job XML 信息
*/
public void getJobConfig(){
try {
String xml = jenkinsServer.getJobXml("test-job");
System.out.println(xml);
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 执行无参数 Job build
*/
public void buildJob(){
try {
jenkinsServer.getJob("test-job").build(true);
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 执行带参数 Job build
*/
public void buildParamJob(){
try {
/**
* 例如,现有一个job,拥有一个字符参数"key"
* 现在对这个值进行设置,然后执行一个输出这个值的脚本
*/
// 设置参数值
Map<String,String> param = new HashMap<>();
param.put("way","gm-R-b");
// 执行 build 任务
jenkinsServer.getJob("das-app-android-pkg").build(param, true);
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 停止最后构建的 Job Build
*/
public void stopLastJobBuild(){
try {
// 获取最后的 build 信息
Build build = jenkinsServer.getJob("test-job").getLastBuild();
// 停止最后的 build
build.Stop();
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 删除 Job
*/
public void deleteJob(){
try {
jenkinsServer.deleteJob("test-job", true);
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 禁用 Job
*/
public void disableJob(){
try {
jenkinsServer.disableJob("test-job", true);
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 启用 Job
*/
public void enableJob(){
try {
jenkinsServer.enableJob("test-job", true);
} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
JobApi jobApi = new JobApi();
// jobApi.getJob();
// jobApi.getJobList();
jobApi.buildParamJob();
// // 创建 Job
// jobApi.ceateJob();
// // 构建无参数的 Job
// jobApi.buildJob();
// // 构建带参数的 Job
// jobApi.buildParamJob();
// // 停止最后构建的 Job Build
// jobApi.stopLastJobBuild();
// // 更新 Job
// jobApi.updateJob();
// // 获取 Job 信息
// jobApi.getJob();
// // 获取 Maven 项目 Job
// jobApi.getMavenJob();
// // 获取 Job 配置xml
// jobApi.getJobConfig();
// 获取全部 Job 列表
// jobApi.getJobList();
// 根据 view 名称获取 Job 列表
// jobApi.getJobListByView();
// // 禁用 Job
// jobApi.disableJob();
// // 启用 Job
// jobApi.enableJob();
// // 删除 Job
// jobApi.deleteJob();
}

}