1.背景 Jenkins具有丰富的插件生态,足以满足我们日常工作的需求;如果我们想通过具体的Jenkins任务直接对外提供服务,而我们不想将内部的具体实现对外暴露(否则,需添加对应的用户权限,通过页面执行job);可以对外直接提供接口,第三方直接调用接口(比如提供给开发,提测前回归冒烟用例集),执行相应的Jenkins任务并获取任务结果。 2.Jenkins原生Remote access APIJenkins提供了原生的Remote accsee API, 主要用来做: 1.检索Jenkins中信息
2.触发新构建
3.创建/复制任务
实例: - 获取项目FastTest信息:
- curl -u user:pwd -X POST http://ip:port/jenkins/job/FastTest/api/xml
- 并支持Xpath进行信息提取,详见 https://issues.jenkins-ci.org/browse/JENKINS-626
- 触发新的构建(带参数构建):
- curl -u user:pwd -X POST http://ip:port/jenkins/job/FastTest/buildWithParameters -d "environment=运行环境&module=模块&mailer=收件人"
- 该接口响应头信息:
- * upload completely sent off: 94 out of 94 bytes
- < HTTP/1.1 201 Created
- < Server: Apache-Coyote/1.1
- < X-Content-Type-Options: nosniff
- < Location: http://ip:port/jenkins/queue/item/111/
- < Content-Length: 0
- < Date: Wed, 05 Oct 2016 07:39:39 GMT
- <
- * Connection #0 to host 10.210.228.50 left intact
- 但是该接口无任何返回信息。
复制代码完整的Remote access API wiki 可以通过如下获取: - curl -u user:pwd -X POST http://ip:port/jenkins/job/FastTest/api/ > /Users/hugang/Desktop/jenkins_api_wiki.html
复制代码原生的接口,功能较为简单、不友好,需封装Jenkins的api,提供有价值的接口返回信息。 3.Jenkins api wrappersJenkins api wrappers有多种编程语言实现, 可以很方便的操作Jenkins,具体如下: Node.js: https://www.npmjs.com/package/jenkins-api ruby: https://rubygems.org/gems/jenkins_api_client python: https://pypi.python.org/pypi/python-jenkins/ java: https://github.com/jenkinsci/java-client-api 本文将使用java的Jenkins api wrappers:java-client-api作为介绍,定制适合自己的Jenkins RESTful API. 4.定制Jenkins RESTful API新建一个Maven webapp工程,工程pom.xml中添加java-client-api依赖: - <dependency>
- <groupId>com.offbytwo.jenkins</groupId>
- <artifactId>jenkins-client</artifactId>
- <version>0.3.6</version>
- </dependency>
复制代码项目使用Spring RESTful web service Controller层执行用例接口: - package com.weibo.qa.fasttestapi.controller;
- import com.weibo.qa.fasttestapi.model.RunInfo;
- import com.weibo.qa.fasttestapi.service.EmailSuffixService;
- import com.weibo.qa.fasttestapi.service.FastTestJenkinsService;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
- /**
- *
- * 接口/fasttest/run:
- *
- * params:
- *
- * env 测试环境
- * module 模块
- * email 收件人
- *
- *
- * result:
- *
- * {"result":true,"jobId":int值}
- *
- * Created by hugang on 16/9/19.
- */
- @RestController
- public class RunController {
- @RequestMapping(value = "/fasttest/run.json", method = RequestMethod.POST)
- public RunInfo runFasttest(@RequestParam(value = "env", required = true) String env,
- @RequestParam(value = "module", required = true, defaultValue = "BVT") String module,
- @RequestParam(value = "email", required = true, defaultValue = "hugang") String email){
- FastTestJenkinsService fastTestJenkinsService = new FastTestJenkinsService();
- // 增加邮箱后缀
- EmailSuffixService emailSuffix = new EmailSuffixService();
- String receiver = emailSuffix.addEmailSuffix(email);
- int jobId = fastTestJenkinsService.buildJob(env, module, receiver);
- RunInfo runInfo = new RunInfo();
- runInfo.setJobId(jobId);
- runInfo.setResult(true);
- return runInfo;
- }
- }
复制代码根据jobId判断是否执行结束接口: - package com.weibo.qa.fasttestapi.controller;
- import com.weibo.qa.fasttestapi.model.FinishInfo;
- import com.weibo.qa.fasttestapi.service.FastTestJenkinsService;
- import org.springframework.web.bind.annotation.*;
- /**
- * Created by hugang on 16/9/20.
- */
- @RestController
- public class FinishController {
- @RequestMapping(value = "/fasttest/finish.json",method = RequestMethod.GET)
- public @ResponseBody
- FinishInfo isFinish(@RequestParam(value = "job_id", required = true)int job_id) {
- FastTestJenkinsService fastTestJenkinsService = new FastTestJenkinsService();
- boolean isFinish = fastTestJenkinsService.isJobFinish(job_id);
- FinishInfo finishInfo = new FinishInfo();
- finishInfo.setFinished(isFinish);
- return finishInfo;
- }
- }
复制代码 service层执行具体的业务:FastTestJenkinsService.java - package com.weibo.qa.fasttestapi.service;
- import com.offbytwo.jenkins.JenkinsServer;
- import com.offbytwo.jenkins.model.Job;
- import com.offbytwo.jenkins.model.JobWithDetails;
- import java.net.URI;
- import java.util.HashMap;
- import java.util.Map;
- /**
- * Created by hugang on 16/9/19.
- */
- public class FastTestJenkinsService {
- /**
- *
- * @param env 测试环境
- * @param module 测试模块
- * @param email 收件人
- * @return jobId
- */
- public int buildJob(String env, String module, String email) {
- int buildNumber = 0;
- try{
- JenkinsServer jenkinsServer = new JenkinsServer(new URI("http://ip:port/jenkins"), "test", "pwd");
- Map<String, Job> jobs = jenkinsServer.getJobs();
- JobWithDetails job = jobs.get("FastTest").details();
- // 即将执行任务的jobId
- buildNumber = job.getNextBuildNumber();
- // 参数化构建
- Map<String, String> params = new HashMap<String, String>();
- params.put("environment", env);
- params.put("module", module);
- params.put("mailer", email);
- job.build(params);
- }catch (Exception e){
- e.printStackTrace();
- } finally {
- }
- return buildNumber;
- }
- /**
- *
- * @param jobId
- * @return 是否执行结束
- */
- public boolean isJobFinish(int jobId) {
- if(jobId <=0){
- throw new IllegalArgumentException("jodId must greater than 0!");
- }
- try{
- JenkinsServer jenkinsServer = new JenkinsServer(new URI("http://ip:port/jenkins"), "user", "pwd");
- Map<String, Job> jobs = jenkinsServer.getJobs();
- JobWithDetails job = jobs.get("FastTest").details();
- boolean isBuilding = job.getBuildByNumber(jobId).details().isBuilding();
- return !isBuilding;
- } catch (Exception e){
- e.printStackTrace();
- } finally{
- }
- return false;
- }
复制代码 model层执行用例返回数据:RunInfo.java - package com.weibo.qa.fasttestapi.model;
- /**
- * 执行用例接口返回的数据
- * Created by hugang on 16/9/19.
- */
- public class RunInfo {
- private boolean result;
- private int jobId;
- public boolean isResult() {
- return result;
- }
- public void setResult(boolean result) {
- this.result = result;
- }
- public int getJobId() {
- return jobId;
- }
- public void setJobId(int jobId) {
- this.jobId = jobId;
- }
- }
- 查看jobId对应的任务是否结束:FinishInfo.java
- package com.weibo.qa.fasttestapi.model;
- /**
- * 查看执行用例是否结束
- * Created by hugang on 16/9/19.
- */
- public class FinishInfo {
- private boolean finished;
- public boolean isFinished() {
- return finished;
- }
- public void setFinished(boolean finished) {
- this.finished = finished;
- }
- }
复制代码
|