前言
目前,我们将要上线DevOps系统,面对未来可能需要对系统的二次开发和处于对系统的深入理解,我需要对Jenkins API有个比较熟悉的了解。在DevOps中,jenkins总是作为其中的一环集成到里面,它提供了几种语言的API,可以很方便的进行调用集成。
一.Jenkins Rest API简单介绍
在githup上,jenkins-rest项目地址:jenkins-rest ,接口定义和接口测试代码都可以详细看到。以下是使用REST API的前置条件:
需要运行着的jenkins环境
需要一个管理员权限的账号
CSRF功能需要关闭掉,不然会影响接口的请求(在API使用JenkinsClient连接后,基于Jenkins API进行请求是没有问题的,也可以不关闭。我是因为需要通过访问post接口创建凭据,所以需要关闭CSRF功能,不然会403。低版本的jenkins可以在 Configure Global Security功能)
重点:config.xml的创建,通过REST API创建job,则需要动态传入和修改Job对应的config.xml,目前主流未提供完整的config.xml生成工具。根据查询到的资料,大部分人都是用固定的xml字符串去修改后再拼接到一起,来构成所需要的config.xml,这并不规范,而且在多种Job类型的场景下,无法根据任务类型生成所需的config.xml。
这里提供一个博主自己在做的开源项目 xml-jenkins,博主会持续维护Jenkins常用的 config.xml。
二.关闭CSRF保护
高版本jenkins,页面因为无关闭CSRF选项了,需要在Manage Jenkins —>Script Console中手动禁用CSRF.
禁用CSRF,命令如下:
hudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION = true
启用CSRF,命令如下:
hudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION = false
三.Jenkins Rest API使用
1.引入 jenkins-rest.jar 包
引入以下依赖:
<dependency>
<groupId>com.cdancy</groupId>
<artifactId>jenkins-rest</artifactId>
<version>0.0.28</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>
2.创建客户端
2.1JenkinsClient
@Configuration
public class JenkinsClient {
@Autowired
private JenkinsProperties jenkinsProperties;
@Bean(name = "jenkinsClient")
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
public JenkinsClient getJenkinsClient() {
return JenkinsClient.builder()
.endPoint(jenkinsProperties.getServerUri())
.credentials(jenkinsProperties.getUsername() + ":" + jenkinsProperties.getPassword())
.build();
}
}
2.2JenkinsProperties
@Data
@Component
@ConfigurationProperties("jenkins")
public class JenkinsProperties {
private String serverUri;
private String username;
private String password;
}
2.3application.yaml
jenkins:
# jenkins的访问url
server-uri: http://127.0.0.1:8080
username: jenkins
password: jenkins
3.API介绍
底层代码:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.cdancy.jenkins.rest;
import com.cdancy.jenkins.rest.features.ConfigurationAsCodeApi;
import com.cdancy.jenkins.rest.features.CrumbIssuerApi;
import com.cdancy.jenkins.rest.features.JobsApi;
import com.cdancy.jenkins.rest.features.PluginManagerApi;
import com.cdancy.jenkins.rest.features.QueueApi;
import com.cdancy.jenkins.rest.features.StatisticsApi;
import com.cdancy.jenkins.rest.features.SystemApi;
import com.cdancy.jenkins.rest.features.UserApi;
import java.io.Closeable;
import org.jclouds.rest.annotations.Delegate;
public interface JenkinsApi extends Closeable {
@Delegate
CrumbIssuerApi crumbIssuerApi();
@Delegate
JobsApi jobsApi();
@Delegate
PluginManagerApi pluginManagerApi();
@Delegate
QueueApi queueApi();
@Delegate
StatisticsApi statisticsApi();
@Delegate
SystemApi systemApi();
@Delegate
ConfigurationAsCodeApi configurationAsCodeApi();
@Delegate
UserApi userApi();
}
由代码可以看出一共提供了6个API类,如下表所示:
API类 | 说明 |
pluginManagerApi | 插件API:提供插件操作接口,一共就俩方法,查看和安装插件 |
crumbIssuerApi | 系统哈希值信息(用于防御CSRF攻击) |
jobsAPi | 任务(项目管理),提供任务的创建、修改、查询、删除等操作,主要使用接口 |
queueApi | 任务队列相关 |
statisticsApi | jenkins统计相关 |
systemApi | jenkins系统信息,如版本 |
API 二次封装:
@Component
public class JenkinsTemplate {
@Autowired
private JenkinsClient jenkinsClient;
/**
* 任务管理(任务信息、创建、修改)API
*/
private JobsApi jobsApi;
/**
* 插件管理(插件信息、安装插件)API
*/
private PluginManagerApi pluginManagerApi;
/**
* 任务队列相关(队列状态)API
*/
private QueueApi queueApi;
/**
* Jenkins统计信息 API
*/
private StatisticsApi statisticsApi;
/**
* 系统哈希值信息(用于防御CSRF攻击)API
*/
private CrumbIssuerApi crumbIssuerApi;
/**
* Jenkins系统状态(版本、路径)API
*/
private SystemApi systemApi;
/**
* jenkins用户信息API
*/
private UserApi userApi;
public JenkinsTemplate() {
}
/**
* 后置处理,JenkinsTemplate比JenkinsProperties先初始化,所以不能在构造器里获取api
*/
@PostConstruct
public void initApi(){
this.jobsApi = jenkinsClient.api().jobsApi();
this.pluginManagerApi = jenkinsClient.api().pluginManagerApi();
this.queueApi = jenkinsClient.api().queueApi();
this.statisticsApi = jenkinsClient.api().statisticsApi();
this.crumbIssuerApi = jenkinsClient.api().crumbIssuerApi();
this.systemApi = jenkinsClient.api().systemApi();
}
}
4.JobsApi-任务API
4.1任务列表查询
/**
* @Title: fetchJobInfo
* @Description: 任务列表查询
* @param: optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @return: JobInfo
* @throws
*/
public JobList getJobInfo(String optionalFolderPath) {
return jobsApi.jobList(optionalFolderPath);
}
4.2获取任务信息
/**
* @Title: fetchJobInfo
* @Description: 获取任务信息
* @param: optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: jobName 任务名
* @return: JobInfo
* @throws
*/
public JobInfo getJobInfo(String optionalFolderPath, String jobName) {
return jobsApi.jobInfo(optionalFolderPath, jobName);
}
4.3 使用 XML 文件创建任务
/**
* @Title: create
* @Description: 使用 XML 文件创建任务
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @param configXML 任务配置
* @param: @return
* @return: RequestStatus
* @throws
*/
public RequestStatus createJob(String optionalFolderPath, String jobName, String configXML) {
return jobsApi.create(optionalFolderPath, jobName, configXML);
}
4.4删除任务
/**
* @Title: deleteJob
* @Description: 删除任务
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @param configXML 任务配置
* @param: @return
* @return: RequestStatus
* @throws
*/
public RequestStatus deleteJob(String optionalFolderPath, String jobName, String configXML) {
return jobsApi.delete(optionalFolderPath, jobName);
}
4.5启用任务
/**
* @Title: deleteJob
* @Description: 启用任务
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @param configXML 任务配置
* @param: @return
* @return: RequestStatus
* @throws
*/
public boolean enableJob(String optionalFolderPath, String jobName, String configXML) {
return jobsApi.enable(optionalFolderPath, jobName);
}
4.6禁用任务
/**
* @Title: disableJob
* @Description: 禁用任务
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @param configXML 任务配置
* @param: @return
* @return: boolean
* @throws
*/
public boolean disableJob(String optionalFolderPath, String jobName, String configXML) {
return jobsApi.disable(optionalFolderPath, jobName);
}
4.7获取任务配置文件内容
/**
* @Title: getConfig
* @Description: 获取任务配置文件内容
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @return
* @return: String
* @throws
*/
public String getJobConfig(String optionalFolderPath, String jobName) {
return jobsApi.config(optionalFolderPath, jobName);
}
4.8更新任务配置文件内容
/**
* @Title: updateConfig
* @Description: 更新任务配置文件
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @param configXML 任务配置
* @param: @return
* @return: boolean
* @throws
*/
public boolean updateJobConfig(String optionalFolderPath, String jobName, String configXML) {
return jobsApi.config(optionalFolderPath, jobName, configXML);
}
4.9获取任务描述内容
/**
* @Title: getJobDescription
* @Description: 获取任务描述内容
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @return
* @return: String
* @throws
*/
public String getJobDescription(String optionalFolderPath, String jobName) {
return jobsApi.description(optionalFolderPath, jobName);
}
4.10设置任务描述内容
/**
* @Title: setJobDescription
* @Description: 设置任务描述
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @param configXML 任务配置
* @param: @return
* @return: boolean
* @throws
*/
public boolean setJobDescription(String optionalFolderPath, String jobName, String configXML) {
return jobsApi.description(optionalFolderPath, jobName, configXML);
}
4.11构建任务
/**
* @Title: buildJob
* @Description: 构建任务
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @return
* @return: IntegerResponse
* @throws
*/
public IntegerResponse buildJob(String optionalFolderPath, String jobName) {
return jobsApi.build(optionalFolderPath, jobName);
}
4.12构建带参数任务
/**
* @Title: buildJobwithParams
* @Description: 构建带参数任务
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @param configXML 任务配置
* @param: @param properties
* @param: @return
* @return: IntegerResponse
* @throws
*/
public IntegerResponse buildJobwithParams(String optionalFolderPath, String jobName, Map<String,List<String>> properties) {
return jobsApi.buildWithParameters(optionalFolderPath, jobName, properties);
}
4.13获取Job上次构建序号
/**
* @Title: lastBuildNumber
* @Description: 获取Job上次构建序号
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @return
* @return: Integer
* @throws
*/
public Integer getLastBuildNumber(String optionalFolderPath, String jobName) {
return jobsApi.lastBuildNumber(optionalFolderPath, jobName);
}
4.14 获取Job上次构建时间戳
/**
* @Title: getLastBuildTimestamp
* @Description: 获取Job上次构建时间戳
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @return
* @return: String
* @throws
*/
public String getLastBuildTimestamp(String optionalFolderPath, String jobName) {
return jobsApi.lastBuildTimestamp(optionalFolderPath, jobName);
}
4.15获取构建信息
/**
* @Title: fetchJobInfo
* @Description: 获取构建信息
* @param: optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: jobName 任务名
* @param: buildNumber 构建序号
* @return: JobInfo
* @throws
*/
public BuildInfo getBuildInfo(String optionalFolderPath, String jobName, int buildNumber) {
return jobsApi.buildInfo(optionalFolderPath, jobName, buildNumber);
}
4.16任务构建对应的控制台输出内容
/**
* @Title: getLogText
* @Description: 任务构建对应的控制台输出内容
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @param start
* @param: @return
* @return: ProgressiveText
* @throws
*/
public ProgressiveText getLogText(String optionalFolderPath, String jobName, int start) {
return jobsApi.progressiveText(optionalFolderPath, jobName, start);
}
4.17 获取指定构建控制台输出
/**
* @Title: getLogTextofBuildNumber
* @Description: 获取指定构建控制台输出
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName 任务名
* @param: @param buildNumber 构建序号
* @param: @param start
* @param: @return
* @return: ProgressiveText
* @throws
*/
public ProgressiveText getLogTextofBuildNumber(String optionalFolderPath, String jobName, int buildNumber, int start) {
return jobsApi.progressiveText(optionalFolderPath, jobName, buildNumber, start);
}
4.18 任务重命名
/**
* @Title: renameJob
* @Description: 任务重命名
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param currentJobName 任务当前名称)
* @param: @param newJobName 任务新名称
* @param: @return
* @return: boolean
* @throws
*/
public boolean renameJob(String optionalFolderPath,String currentJobName, String newJobName) {
return jobsApi.rename(optionalFolderPath, currentJobName, newJobName);
}
4.19任务某次构建的步骤信息
/**
* @Title: workflow
* @Description: 任务某次构建的步骤信息
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName (任务名)
* @param: @param buildNumber (任务新名称)
* @param: @return
* @return: Workflow
* @throws
*/
public Workflow workflow(String optionalFolderPath,String JobName, int buildNumber) {
return jobsApi.workflow(optionalFolderPath, JobName, buildNumber);
}
4.20 获取pipelineNode信息
/**
* @Title: getPipelineNode
* @Description: 获取pipelineNode信息
* @param: @param optionalFolderPath 文件夹名称(对应的是 folder 类型的item)
* @param: @param jobName (任务名)
* @param: @param buildNumber (任务新名称)
* @param: @return
* @return: ProgressiveText
* @throws
*/
public PipelineNode getPipelineNode(String optionalFolderPath,String JobName, int buildNumber) {
return jobsApi.pipelineNode(optionalFolderPath, JobName, buildNumber);
}
5.systemApi-系统环境API
未完待续……