使用Java调用Jenkins REST API
编辑前言
项目中使用到了Jenkins GitHub Organization中的一个开源的Java工具java-client-api来调用Jenkins REST API,其实底层也都是http的调用,这边我简单总结一下项目中用到的一些方法。
- java-client-api地址:https://github.com/jenkinsci/java-client-api
- 博客中的项目代码:https://github.com/yzh19961031/blogDemo/tree/master/jenkins_api
配置信息
- maven工程可以直接引用下面的坐标导入依赖。
<dependency>
<groupId>com.offbytwo.jenkins</groupId>
<artifactId>jenkins-client</artifactId>
<version>0.3.8</version>
</dependency>
常用的一些API
这边总结了大概几类,因为项目中都是对于Job任务的调用,所以我都是总结的关于Job的一些API。 java-client-api主要是要初始化一个JenkinsServer实例,然后这个实例基本上包含了Jenkins的所有方法,使用起来还是比较简单的。
- 初始化以及关闭JenkinsServer
private JenkinsServer server;
@Before
public void testBefore() throws URISyntaxException {
this.server = new JenkinsServer(new URI(JENKINS_URL), JENKINS_USERNAME, JENKINS_PASSWORD);
}
@After
public void testAfter() {
if (server != null) {
server.close();
}
}
- 获取Job信息
// 测试获取所有的Job任务
@Test
public void testGetAllJobs() throws IOException {
Map<String, Job> jobs = server.getJobs();
for (Map.Entry<String,Job> job:jobs.entrySet()) {
log.info("jobName is {}",job.getKey());
}
}
// 获取Job的一些属性信息
@Test
public void testGetJob() throws IOException {
String jobXml = server.getJobXml(JENKINS_PROJECT_NAME);
// 获取job的xml信息
log.info("jenkins job xml is {}", jobXml);
}
- 创建job任务 这边注意一下,对于不是GET的请求,要将crumbFlag设置为true,或者在Jenkins页面上关闭csrf防护。(不推荐)
// 创建Jenkins Job任务
@Test
public void testCreateJob() throws IOException {
// 这边要注意一下,需要设置crumbFlag为true,这样会添加一个crumb头
// 之前的大家的做法也都是去关闭csrf防护,但是如果为了安全,还是建议打开,只需要每次调用接口的时候添加下crumb头就可以了
server.createJob(JENKINS_PROJECT_NAME,JENKINS_PROJECT_XML,true);
}
- 删除任务
// 删除任务
@Test
public void testDeleteJob() throws IOException {
server.deleteJob(JENKINS_PROJECT_NAME, true);
}
- 修改任务
// 修改任务
@Test
public void testUpdateJob() throws IOException {
// 这边测试用 原地更新
server.updateJob(JENKINS_PROJECT_NAME,JENKINS_PROJECT_XML,true);
}
- 构建任务并且获得本次构建的buildNumber(业务场景)
/**
* 构建任务并且返回当前构建的buildNumber
* * @param jobName 任务名称
* @param parameters 构建参数
* @return 当前任务的buildNumber
* @throws IOException
*/
private Long buildJob(String jobName, Map<String,String> parameters) throws IOException {
// 1.获取Job信息
JobWithDetails job = server.getJob(jobName);
// 2.使用构建参数执行本次构建
QueueReference queueReference = job.build(parameters,true);
QueueItem queueItem = server.getQueueItem(queueReference);
// 3.获取构建的buildNumber
Executable executable = queueItem.getExecutable();
// 这边需要进行一下轮训
while (executable == null) {
executable = server.getQueueItem(queueReference).getExecutable();
sleep();
log.info("time waiting");
}
Long number = executable.getNumber();
log.info("this time build number is {}", number);
return number;
}
- 终止任务
// 测试终止任务
@Test
public void testAbortedJob() throws IOException {
// 这边测试终止 我在shell的构建里面添加了延时
Map<String,String> param = new HashMap<>();
param.put("name","yuan");
Long buildNumber = buildJob(JENKINS_PROJECT_NAME, param);
JobWithDetails job = server.getJob(JENKINS_PROJECT_NAME);
Build build = job.getBuildByNumber(buildNumber.intValue());
// 停止任务 这边停止任务没有返回值 但是可以获取到当前任务的构建状态
build.Stop(true);
BuildResult result = build.details().getResult();
log.info("stop job, job status is {}", result.toString());
}
- 获取构建的相关信息
// 获取构建的一些信息
@Test
public void testGetBuildingInformation() throws IOException {
JobWithDetails job = server.getJob(JENKINS_PROJECT_NAME);
// 获取最后一次构建的输出
Build lastBuild = job.getLastBuild();
BuildWithDetails details = lastBuild.details();
// 控制台日志
String consoleOutputText = details.getConsoleOutputText();
log.info("this time consoleOutputText is {}",consoleOutputText);
// 构建结果
BuildResult result = details.getResult();
log.info("this time build rest is {}",result.toString());
// 本次构建的参数
Map<String, String> parameters = details.getParameters();
log.info("this time build parameters is {}",parameters);
}
直接使用http方式调用
当然,java-client-api可能也有一些不满足的场景,这种就需要我们自己实现来调用Jenkins REST API了,其实也很简单,自己实现一下http调用就行了,使用Java原生提供的方式或者httpclient都可以。我这边用httpclient简单封装了一下调用的方法。
- http调用公共方法
/**
* 单独提取的一个公共方法
* * @param url 请求地址
* @param httpRequest 请求方法对象
* @return
*/
private String customHttpMsg(String url, HttpRequest httpRequest) throws URISyntaxException, IOException {
URI uri = new URI(url);
HttpHost host = new HttpHost(uri.getHost(), uri.getPort());
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
// 这边需要注意一下是使用的token代替了密码 后续会整理下项目中遇到的一个问题
credentialsProvider.setCredentials(new AuthScope(uri.getHost(), uri.getPort()),
new UsernamePasswordCredentials(JENKINS_USERNAME, JENKINS_TOKEN));
AuthCache authCache = new BasicAuthCache();
BasicScheme basicScheme = new BasicScheme();
authCache.put(host,basicScheme);
try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(credentialsProvider).build()) {
HttpClientContext httpClientContext = HttpClientContext.create();
httpClientContext.setAuthCache(authCache);
CloseableHttpResponse response = httpClient.execute(host, httpRequest, httpClientContext);
return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
}
}
- 调用 这边就简单贴下代码了。方法都是测试可行的。
// 获取Job信息
@Test
public void testGetJob1() throws IOException, URISyntaxException {
String url = JENKINS_URL+"/job/"+JENKINS_PROJECT_NAME+"/config.xml";
HttpGet httpGet = new HttpGet(url);
String res = customHttpMsg(url, httpGet);
log.info("res is {}", res);
}
// 删除任务
@Test
public void testDeleteJob1() throws IOException, URISyntaxException {
String url = JENKINS_URL+"/job/"+JENKINS_PROJECT_NAME+"/doDelete/api/json";
HttpPost httpPost = new HttpPost(url);
String res = customHttpMsg(url, httpPost);
log.info("res is {}", res);
}
// 创建任务
@Test
public void testCreateJob1() throws IOException, URISyntaxException {
// http://192.168.1.107:8081/jenkins/createItem/api/json?name=test
String url = JENKINS_URL+"/createItem/api/json?name="+JENKINS_PROJECT_NAME;
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new StringEntity(JENKINS_PROJECT_XML, ContentType.create("text/xml", "utf-8")));
String res = customHttpMsg(url, httpPost);
log.info("res is {}", res);
}