长春网站制作设计,做ppt的网站,建设银行网站查询房贷信息,腾讯小程序怎么制作使用Jenkins CLI进行二次开发
使用背景
公司自研CI/DI平台#xff0c;借助JenkinsSonarQube进行代码质量管理。对接版本
Jenkins版本为#xff1a;Version 2.428
SonarQube版本为#xff1a;Community EditionVersion 10.2.1 (build 78527)技术选型
Java对接Jenkins有第…使用Jenkins CLI进行二次开发
使用背景
公司自研CI/DI平台借助JenkinsSonarQube进行代码质量管理。对接版本
Jenkins版本为Version 2.428
SonarQube版本为Community EditionVersion 10.2.1 (build 78527)技术选型
Java对接Jenkins有第三方组件比如jenkins-rest、jenkins-client但是考虑到第三方组件会引入其他jar包而且会存在漏洞问题。
到时候升级组件时可能会和项目框架本身使用的第三方jar起冲突。因此使用jenkins-cli来实现自己的需求。注意这里不是单纯的使用java -jar jenkins-cli.jar -http xxxx来实现接口调用
而且提取并修改jenkins-cli.jar中的源码来达到自身需求开发的目的。
比如创建View时使用jenkins-cli.jar时需要传入xml内容标准输入流
所以我们进行了改造可以支持传入byte数组的形式使用体验更符合大众。jenkins-cli.jar的源码修改 package com.infosec.autobuild.util;import com.cdancy.jenkins.rest.JenkinsClient;
import com.cdancy.jenkins.rest.domain.job.BuildInfo;
import com.cdancy.jenkins.rest.domain.queue.QueueItem;
import com.infosec.autobuild.dto.*;
import com.infosec.autobuild.dto.jenkins.BuildInfoDto;
import com.infosec.autobuild.dto.jenkins.CredentialDto;
import com.infosec.autobuild.dto.jenkins.JobDto;
import com.infosec.autobuild.dto.jenkins.ViewDto;
import com.infosec.autobuild.hudson.cli.CLI;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** Jenkins cli工具类*/
Slf4j
public class JenkinsUtil {private static final String PROTOCOL_HTTP -http;private static final String PROTOCOL_WEB_SOCKET -webSocket;/*** 结束符\r\n*/private static final String END_SYMBOL \\r\\n;/*** 换行符:\n*/private static final String LINE_BREAK_SYMBOL \\n;/*** Jenkins 凭证相关操作暂不包括domain相关操作*/public static class Credentials {/*** system::system::jenkins等同于SystemCredentialsProvider::SystemContextResolver::jenkins* Provider可以通过java -jar jenkins-cli.jar -auth admin:admin -s http://xxx:8080/ -http list-credentials-providers获取* Resolver可以通过java -jar jenkins-cli.jar -auth admin:admin -s http://xxx:8080/ -http list-credentials-context-resolvers获取*/private static final String SYSTEM_STORE_ID system::system::jenkins;/*** 默认全局domain*/private static final String GLOBAL_DOMAIN (global);private static final String CREDENTIAL_NOT_FOUND No such credential;enum Operation {/*** 查询Jenkins Credentials集合:list-credentials*/LIST_CREDENTIALS(list-credentials, 查询Jenkins Credentials集合),/*** 查询Jenkins Credentials集合返回xml:list-credentials-as-xml*/LIST_CREDENTIALS_AS_XML(list-credentials-as-xml, 查询Jenkins Credentials集合返回xml),/*** 创建Jenkins Credentials:create-credentials-by-xml*/CREATE_CREDENTIALS(create-credentials-by-xml, 创建Jenkins Credentials),/*** 更新Jenkins Credentials:create-credentials-by-xml*/UPDATE_CREDENTIALS(update-credentials-by-xml, 更新Jenkins Credentials),/*** 删除Jenkins Credentials:delete-credentials*/DELETE_CREDENTIALS(delete-credentials, 删除Jenkins Credentials),/*** 查询Jenkins Credentials:get-credentials-as-xml*/GET_CREDENTIALS(get-credentials-as-xml, 查询Jenkins Credentials),;SetterGetterprivate String op;SetterGetterprivate String desc;Operation(String op, String desc) {this.setOp(op);this.setDesc(desc);}}/*** 创建Jenkins 凭证凭证id为空时默认使用36位UUID** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param credentialDto 凭证对象* return ResultDto*/public static ResultDto createCredential(String host, String auth, CredentialDto credentialDto) {if (!StringUtils.hasText(credentialDto.getId())) {credentialDto.setId(UUID.randomUUID().toString());}String xml CredentialDto.parseDto2Xml(credentialDto);CLI cli doWork(host, auth, new String[]{Operation.CREATE_CREDENTIALS.op, SYSTEM_STORE_ID, }, PROTOCOL_HTTP, xml);int code cli.code;String msg cli.msg;return ResultDto.SUCCESS.equals(String.valueOf(code)) ?ResultDto.buildSuccessDto() : ResultDto.buildErrorDto().msg(msg);}/*** 删除Jenkins 凭证** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param credentialId 凭证id* return ResultDto*/public static ResultDto deleteCredential(String host, String auth, String credentialId) {CLI cli doWork(host, auth,new String[]{Operation.DELETE_CREDENTIALS.op, SYSTEM_STORE_ID, , credentialId},PROTOCOL_HTTP, null);int code cli.code;String msg cli.msg;if (StringUtils.hasText(msg) msg.contains(CREDENTIAL_NOT_FOUND)) {return ResultDto.buildSuccessDto();}return ResultDto.SUCCESS.equals(String.valueOf(code)) ?ResultDto.buildSuccessDto() : ResultDto.buildErrorDto().msg(msg);}/*** 更新Jenkins 凭证凭证id无法修改** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param credentialDto 凭证对象* return ResultDto*/public static ResultDto updateCredential(String host, String auth, CredentialDto credentialDto) {if (!StringUtils.hasText(credentialDto.getId())) {return ResultDto.buildErrorDto().msg(凭证id不能为空);}String xml CredentialDto.parseDto2Xml(credentialDto);CLI cli doWork(host, auth, new String[]{Operation.UPDATE_CREDENTIALS.op, SYSTEM_STORE_ID,GLOBAL_DOMAIN, credentialDto.getId()}, PROTOCOL_HTTP, xml);int code cli.code;String msg cli.msg;if (StringUtils.hasText(msg) msg.contains(CREDENTIAL_NOT_FOUND)) {msg 根据凭证id未找到对应记录;return ResultDto.buildErrorDto().msg(msg);}return ResultDto.SUCCESS.equals(String.valueOf(code)) ?ResultDto.buildSuccessDto() : ResultDto.buildErrorDto().msg(msg);}/*** 查询Jenkins 凭证** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param credentialId 凭证id* return ResultDto*/public static ResultDtoCredentialDto getCredential(String host, String auth, String credentialId) {CLI cli doWork(host, auth,new String[]{Operation.GET_CREDENTIALS.op, SYSTEM_STORE_ID, , credentialId},PROTOCOL_HTTP, null);int code cli.code;String msg cli.msg;if (StringUtils.hasText(msg) msg.contains(CREDENTIAL_NOT_FOUND)) {msg 根据凭证id未找到对应记录;return ResultDto.buildErrorDto().msg(msg);}boolean ifSuccess ResultDto.SUCCESS.equals(String.valueOf(code));CredentialDto credentialDto new CredentialDto();if (ifSuccess) {if (StringUtils.hasText(msg)) {CredentialDto.parseXmlStr2Dto(credentialDto, msg, null);}}return ifSuccess ? ResultDto.buildSuccess(credentialDto) : ResultDto.buildError(credentialDto).msg(msg);}/*** 查询Jenkins上的凭证列表** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* return ResultDto*/public static ResultDtoListCredentialDto listCredentials(String host, String auth) {CLI cli doWork(host, auth, new String[]{Operation.LIST_CREDENTIALS_AS_XML.op, SYSTEM_STORE_ID},PROTOCOL_HTTP, null);int code cli.code;String msg cli.msg;ListCredentialDto credentialDtoList new ArrayList(10);boolean ifSuccess ResultDto.SUCCESS.equals(String.valueOf(code));if (ifSuccess) {CredentialDto.parseXmlStr2List(credentialDtoList, msg);}return ifSuccess ? ResultDto.buildSuccess(credentialDtoList) : ResultDto.buildError(credentialDtoList).msg(msg);}/*** 查询Jenkins上的凭证列表** param ip Jenkins服务IP* param port Jenkins服务端口* param username Jenkins服务登录用户名* param password Jenkins服务登录密码* return ResultDto*/public static ResultDto listCredentials(String ip, String port, String username, String password) {String host http:// ip : port;String auth username : password;return listCredentials(host, auth);}}/*** Jenkins Job相关操作即Item*/public static class Jobs {private static String JOB_BUILD_DETAIL_URL host/job/jobName/buildId/api/json;private static String QUEUE_LIST_URL host/job/jobName/buildId/api/json;enum Operation {/*** 创建Jenkins Job*/CREATE(create-job, 创建Jenkins Job),/*** 复制Jenkins Job*/COPY(copy-job, 复制Jenkins Job),/*** 更新Jenkins Job*/UPDATE(update-job, 更新Jenkins Job),/*** 删除Jenkins Job*/DELETE(delete-job, 删除Jenkins Job),/*** 构建Jenkins Job*/BUILD(build, 构建Jenkins Job),/*** Jenkins Job构建日志输出*/CONSOLE(console, Jenkins Job构建日志输出),/*** 查询Jenkins Job集合*/LIST(list-jobs, 查询Jenkins Job集合),/*** 查询Jenkins Job*/GET(get-job, 查询Jenkins Job),/*** 将Jenkins Job添加到视图中*/ADD_TO_VIEW(add-job-to-view, 将Jenkins Job添加到视图中),/*** 将Jenkins Job从视图中移除*/REMOVE_FROM_VIEW(remove-job-from-view, 将Jenkins Job从视图中移除),/*** 启用Jenkins Job*/ENABLE(enable-job, 启用Jenkins Job),/*** 禁用Jenkins Job*/DISABLE(disable-job, 禁用Jenkins Job),/*** 重新加载Jenkins Job*/RELOAD(reload-job, 重新加载Jenkins Job),/*** 停止构建Jenkins Jobs*/STOP_BUILDS(stop-builds, 停止构建Jenkins Job);SetterGetterprivate String op;SetterGetterprivate String desc;Operation(String op, String desc) {this.setOp(op);this.setDesc(desc);}}/*** 查询Jenkins上的Job列表** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param viewName Jenkins视图名称为空时查询全部Jobs* return ResultDto*/public static ResultDto listJobs(String host, String auth, String viewName) {String[] baseArgs new String[]{Operation.LIST.op};String[] finalArgs StringUtils.hasText(viewName) ? Stream.concat(Arrays.stream(baseArgs),Arrays.stream(new String[]{viewName})).toArray(String[]::new) : baseArgs;CLI cli doWork(host, auth, finalArgs, PROTOCOL_HTTP, null);int code cli.code;String msg cli.msg;ListJobDto jobDtoList new ArrayList(10);boolean ifSuccess ResultDto.SUCCESS.equals(String.valueOf(code));boolean listAllJobs StringUtils.hasText(viewName) ? true : false;if (ifSuccess) {if (StringUtils.hasText(msg)) {String[] arr msg.split(END_SYMBOL);for (String tmp : arr) {JobDto jobDto new JobDto();jobDto.setJobName(tmp);jobDto.setViewName(listAllJobs ? viewName : );jobDtoList.add(jobDto);}}}return ifSuccess ? ResultDto.buildSuccess(jobDtoList) : ResultDto.buildError(jobDtoList).msg(msg);}/*** 查询Jenkins上的凭证列表** param ip Jenkins服务IP* param port Jenkins服务端口* param username Jenkins服务登录用户名* param password Jenkins服务登录密码* param viewName Jenkins视图名称为空时查询全部Jobs* return ResultDto*/public static ResultDto listJobs(String ip, String port, String username, String password, String viewName) {String host http:// ip : port;String auth username : password;return listJobs(host, auth, viewName);}public static ResultDto addJob2View(String host, String auth, String viewName, String[] jobNames) {String[] baseArgs new String[]{Operation.ADD_TO_VIEW.op};String[] finalArgs Stream.of(baseArgs, new String[]{viewName}, jobNames).flatMap(Arrays::stream).toArray(String[]::new);CLI cli doWork(host, auth, finalArgs, PROTOCOL_HTTP, null);int code cli.code;String msg cli.msg;ListJobDto jobDtoList new ArrayList(10);return ResultDto.SUCCESS.equals(String.valueOf(code)) ?ResultDto.buildSuccess(jobDtoList) : ResultDto.buildError(jobDtoList).msg(msg);}public static ResultDto addJob2View(String ip, String port, String username, String password,String viewName, String[] jobNames) {String host http:// ip : port;String auth username : password;return addJob2View(host, auth, viewName, jobNames);}public static ResultDto removeJobFromView(String host, String auth, String viewName, String[] jobNames) {String[] baseArgs new String[]{Operation.REMOVE_FROM_VIEW.op};String[] finalArgs Stream.of(baseArgs, new String[]{viewName}, jobNames).flatMap(Arrays::stream).toArray(String[]::new);CLI cli doWork(host, auth, finalArgs, PROTOCOL_HTTP, null);int code cli.code;String msg cli.msg;ListJobDto jobDtoList new ArrayList(10);return ResultDto.SUCCESS.equals(String.valueOf(code)) ?ResultDto.buildSuccess(jobDtoList) : ResultDto.buildError(jobDtoList).msg(msg);}/*** 创建Job** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param job Jenkins Job* return {link ResultDto}*/public static ResultDto createJob(String host, String auth, JobDto job) {ListJobDto.SvnInfoDto svnInfoDtoList job.getSvnInfoList();ListJobDto.GitInfoDto gitInfoDtoList job.getGitInfoList();boolean scmCheck CollectionUtils.isEmpty(svnInfoDtoList) CollectionUtils.isEmpty(gitInfoDtoList);if (scmCheck) {return ResultDto.buildErrorDto().msg(源码管理地址信息不能为空);}String xml ?xml version1.1 encodingUTF-8?\n project\n actions/\n description job.getDescription() /description\n keepDependenciesfalse/keepDependencies\n properties/\n;if (!CollectionUtils.isEmpty(svnInfoDtoList)) {xml buildSvn(job);}if (!CollectionUtils.isEmpty(gitInfoDtoList)) {xml buildGit(job);}xml /locations\n excludedRegions/excludedRegions\n includedRegions/includedRegions\n excludedUsers/excludedUsers\n excludedRevprop/excludedRevprop\n excludedCommitMessages/excludedCommitMessages\n workspaceUpdater class\hudson.scm.subversion.UpdateUpdater\/\n ignoreDirPropChangesfalse/ignoreDirPropChanges\n filterChangelogfalse/filterChangelog\n quietOperationtrue/quietOperation\n /scm\n canRoamtrue/canRoam\n disabled job.getDisabled() /disabled\n blockBuildWhenDownstreamBuildingfalse/blockBuildWhenDownstreamBuilding\n blockBuildWhenUpstreamBuildingfalse/blockBuildWhenUpstreamBuilding\n triggers/\n concurrentBuildfalse/concurrentBuild\n;xml buildBuilders(job);xml publishers/\n buildWrappers/\n /project;CLI cli doWork(host, auth, new String[]{Operation.CREATE.op, job.getJobName()}, PROTOCOL_HTTP, xml);int code cli.code;String msg cli.msg;return ResultDto.SUCCESS.equals(String.valueOf(code)) ?ResultDto.buildSuccessDto() : ResultDto.buildErrorDto().msg(msg);}/*** 更新Job** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param job Jenkins Job* return {link ResultDto}*/public static ResultDto updateJob(String host, String auth, JobDto job) {//TODO:待补充完善return null;}/*** 删除单个或多个Job** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param jobNames Jenkins Job名称集* return {link ResultDto}*/public static ResultDto deleteJob(String host, String auth, String[] jobNames) {String[] finalArgs Stream.of(new String[]{Operation.DELETE.op}, jobNames).flatMap(Arrays::stream).toArray(String[]::new);return operation(host, auth, finalArgs);}/*** 复制Job** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param srcJobName 需要被复制的Jenkins Job名称* param destJobName 新Jenkins Job名称* return {link ResultDto}*/public static ResultDto copyJob(String host, String auth, String srcJobName, String destJobName) {String[] finalArgs new String[]{Operation.COPY.op, srcJobName, destJobName};return operation(host, auth, finalArgs);}/*** 查询单个Job** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param jobName Jenkins Job名称* return {link ResultDto}*/public static ResultDtoJobDto getJob(String host, String auth, String jobName) {String[] finalArgs new String[]{Operation.GET.op, jobName};ResultDto resultDto operation(host, auth, finalArgs);JobDto jobDto new JobDto();jobDto.setJobName(jobName);//解析xml获取名称、描述等信息String msg ObjectUtils.isEmpty(resultDto.getData()) ? : resultDto.getData().toString();if (StringUtils.hasText(msg)) {jobDto.parseXmlStr2Dto(msg);}return resultDto.data(jobDto);}/*** 构建单个Job** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param jobName Jenkins Job名称* return {link ResultDto}*/public static ResultDto buildJob(String host, String auth, String jobName) {return operation(host, auth, new String[]{Operation.BUILD.op, jobName});}/*** 输出单个Job的构建日志信息** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param jobName Jenkins Job名称* param buildId 构建id为空时查询最后一次构建的信息* return {link ResultDto}*/public static ResultDto console(String host, String auth, String jobName, Integer buildId) {String[] baseArgs new String[]{Operation.CONSOLE.op, jobName};String[] finalArgs ObjectUtils.isEmpty(buildId) ? baseArgs : Stream.of(baseArgs, new String[]{buildId.toString()}).flatMap(Arrays::stream).toArray(String[]::new);return operation(host, auth, finalArgs);}/*** 禁用Job** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param jobName Jenkins Job名称* return {link ResultDto}*/public static ResultDto disableJob(String host, String auth, String jobName) {return operation(host, auth, new String[]{Operation.DISABLE.op, jobName});}/*** 启用Job** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param jobName Jenkins Job名称* return {link ResultDto}*/public static ResultDto enableJob(String host, String auth, String jobName) {return operation(host, auth, new String[]{Operation.ENABLE.op, jobName});}/*** 重新加载Job** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param jobName Jenkins Job名称* return {link ResultDto}*/public static ResultDto reloadJob(String host, String auth, String jobName) {return operation(host, auth, new String[]{Operation.RELOAD.op, jobName});}/*** 停止构建Job** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param jobNames Jenkins Job名称集合* return {link ResultDto}*/public static ResultDto stopBuildJob(String host, String auth, String[] jobNames) {String[] finalArgs Stream.of(new String[]{Operation.STOP_BUILDS.op}, jobNames).flatMap(Arrays::stream).toArray(String[]::new);return operation(host, auth, finalArgs);}/*** 获取Jenkins Job的构建信息** param host Jenkins地址比如http://10.100.57.156:8080* param username Jenkins登录用户名* param password Jenkins登录用户密码* param jobName Jenkins Job名称* param buildId Jenkins Job构建id* return {link ResultDto}*/public static ResultDtoBuildInfoDto getJobBuildInfoDetail(String host, String username, String password,String jobName, Integer buildId) {if (ObjectUtils.isEmpty(buildId)) {return ResultDto.buildErrorDto().msg(buildId can not empty.);}JenkinsClient client JenkinsClient.builder().endPoint(host).credentials(username : password).build();ListQueueItem list client.api().queueApi().queue();for (QueueItem item : list) {System.out.println(item.why() item.task().name());}System.out.println(JsonUtil.toJSONString(client.api().systemApi().systemInfo()));BuildInfo data client.api().jobsApi().buildInfo(null, jobName, buildId);System.out.println(data.building());String url JOB_BUILD_DETAIL_URL.replace(host, host).replace(jobName, jobName).replace(buildId, buildId.toString());return doGet(url, username, password, BuildInfoDto.class);}/*** 获取Jenkins Job的构建信息** param host Jenkins地址比如http://10.100.57.156:8080* param username Jenkins登录用户名* param password Jenkins登录用户密码* param jobName Jenkins Job名称* param buildId Jenkins Job构建id* return {link ResultDto}*/public static boolean getJobBuildStatus(String host, String username, String password,String jobName, Integer buildId) {if (ObjectUtils.isEmpty(buildId)) {throw new IllegalArgumentException(buildId can not empty.);}String url JOB_BUILD_DETAIL_URL.replace(host, host).replace(jobName, jobName).replace(buildId, buildId.toString());BuildInfoDto infoDto getJobBuildInfoDetail(url, username, password, jobName, buildId).getData();return infoDto.getBuilding();}/*** 操作单个Job查询、启用、禁用、删除** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param args Jenkins CLI参数* return {link ResultDto}*/private static ResultDto operation(String host, String auth, String[] args) {CLI cli doWork(host, auth, args, PROTOCOL_HTTP, null);int code cli.code;String msg cli.msg;return ResultDto.SUCCESS.equals(String.valueOf(code)) ?ResultDto.buildSuccess(msg) : ResultDto.buildError(msg).msg(msg);}/*** 组织Job的git xml章节内容** param job JobDto* return {link String}*/private static String buildGit(JobDto job) {//TODO:待补充组装git相关xml配置String xml ;return xml;}/*** 组织Job的svn xml章节内容** param job JobDto* return {link String}*/private static String buildSvn(JobDto job) {ListJobDto.SvnInfoDto svnInfoDtoList job.getSvnInfoList();String xml scm class\hudson.scm.SubversionSCM\ \n locations\n;StringBuilder sb new StringBuilder();for (JobDto.SvnInfoDto svnInfoDto : svnInfoDtoList) {sb.append( hudson.scm.SubversionSCM_-ModuleLocation\n).append( remote svnInfoDto.getRemote() /remote\n).append( credentialsId svnInfoDto.getCredentialsId() /credentialsId\n).append( local svnInfoDto.getLocal() /local\n).append( depthOption svnInfoDto.getDepthOption() /depthOption\n).append( ignoreExternalsOption svnInfoDto.getIgnoreExternalsOption() /ignoreExternalsOption\n).append( cancelProcessOnExternalsFail svnInfoDto.getCancelProcessOnExternalsFail() /cancelProcessOnExternalsFail\n).append( /hudson.scm.SubversionSCM_-ModuleLocation\n);}xml sb.toString();return xml;}/*** 组织Job的builders xml章节内容** param job JobDto* return {link String}*/private static String buildBuilders(JobDto job) {String xml ;ListString shellList job.getBuildCmdList();ListJobDto.SonarRunnerBuilderDto sonarRunnerBuilderDtoList job.getSonarRunnerBuilderDtoList();boolean checkBuilders CollectionUtils.isEmpty(shellList) CollectionUtils.isEmpty(sonarRunnerBuilderDtoList);if (checkBuilders) {xml builders/;} else {xml builders\n;if (!CollectionUtils.isEmpty(shellList)) {String shells shellList.stream().collect(Collectors.joining(\n));xml hudson.tasks.Shell\n command shells /command\n configuredLocalRules/\n /hudson.tasks.Shell\n;}if (!CollectionUtils.isEmpty(sonarRunnerBuilderDtoList)) {JobDto.ProjectInfo projectInfo job.getProjectInfo();String keyInfo projectInfo.getProjectName() _ job.getJobName() _ projectInfo.getBuildVersion();StringBuilder sb new StringBuilder();for (JobDto.SonarRunnerBuilderDto sonar : sonarRunnerBuilderDtoList) {sb.append( hudson.plugins.sonar.SonarRunnerBuilder\n).append( project/project\n).append( propertiessonar.projectKey keyInfo \n).append(sonar.projectName keyInfo \n).append(sonar.projectVersion projectInfo.getBuildVersion() \n).append(sonar.language sonar.getSonarScannerLanguage() \n).append(sonar.sourceEncodingUTF-8\n).append(sonar.java.binariestarget/classes\n).append(sonar.sources.\n).append(sonar.login job.getSonarLogin() \n).append(sonar.password job.getSonarPassword() \n).append(sonar.scm.disabled sonar.getSonarScmDisabled()).append( /properties\n).append( javaOpts sonar.getJavaOpts() /javaOpts\n).append( additionalArguments sonar.getAdditionalArguments() /additionalArguments\n).append( jdk sonar.getJdk() /jdk\n).append( task sonar.getTask() /task\n).append( /hudson.plugins.sonar.SonarRunnerBuilder\n);}xml sb.toString();}xml /builders\n;}return xml;}}public static class Views {public enum Operation {/*** 创建Jenkins视图*/CREATE(create-view, 创建Jenkins视图),/*** 更新Jenkins视图*/UPDATE(update-view, 更新Jenkins视图),/*** 删除Jenkins视图*/DELETE(delete-view, 删除Jenkins视图),/*** 查询Jenkins视图*/GET(get-view, 查询Jenkins视图);SetterGetterprivate String op;SetterGetterprivate String desc;Operation(String op, String desc) {this.setOp(op);this.setDesc(desc);}}/*** 创建View** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param viewDto ViewDto* return {link ResultDto}*/public static ResultDto createView(String host, String auth, ViewDto viewDto) {return operation(host, auth, viewDto, Operation.CREATE);}/*** 更新View** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param viewDto ViewDto* return {link ResultDto}*/public static ResultDto updateView(String host, String auth, ViewDto viewDto) {return operation(host, auth, viewDto, Operation.UPDATE);}/*** 删除View** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param viewDto ViewDto* return {link ResultDto}*/public static ResultDto deleteView(String host, String auth, ViewDto viewDto) {return operation(host, auth, viewDto, Operation.DELETE);}/*** 重命名View** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param oldViewName Jenkins旧视图名称* param newViewName Jenkins新视图名称* return ResultDto*/public static ResultDto rename(String host, String auth, String oldViewName, String newViewName) {return copyOrRenameView(host, auth, oldViewName, newViewName, true);}/*** 拷贝View** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param oldViewName Jenkins旧视图名称* param newViewName Jenkins新视图名称* return ResultDto*/public static ResultDto copyView(String host, String auth, String oldViewName, String newViewName) {return copyOrRenameView(host, auth, oldViewName, newViewName, false);}/*** 根据视图名称查询视图信息** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param viewName Jenkins视图名称* param returnJobDetails 是否返回Job详细信息默认不返回。* return {link ResultDto}*/public static ResultDtoViewDto getView(String host, String auth, String viewName, Boolean returnJobDetails) {if (!StringUtils.hasText(viewName)) {return ResultDto.buildErrorDto().msg(视图名称不能为空);}CLI cli doWork(host, auth, new String[]{Operation.GET.op, viewName}, PROTOCOL_HTTP, null);int code cli.code;String msg cli.msg;boolean ifSuccess ResultDto.SUCCESS.equals(String.valueOf(code));ViewDto viewDto new ViewDto();viewDto.setViewName(viewName);//解析xml获取view名称、描述、关联的job等信息if (StringUtils.hasText(msg)) {viewDto.parseXmlStr2Dto(msg);}if (ObjectUtils.isEmpty(returnJobDetails)) {returnJobDetails false;}if (returnJobDetails) {ListJobDto jobDtoList viewDto.getJobList();for (JobDto jobDto : jobDtoList) {String jobName jobDto.getJobName();JobDto dto Jobs.getJob(host, auth, jobName).getData();BeanUtils.copyProperties(dto, jobDto);}}return ifSuccess ? ResultDto.buildSuccess(viewDto) : ResultDto.buildError(viewDto).msg(msg);}/*** 拷贝或重命名View** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param oldViewName Jenkins旧视图名称* param newViewName Jenkins新视图名称* return ResultDto*/private static ResultDto copyOrRenameView(String host, String auth, String oldViewName, String newViewName, boolean rename) {//1、先查询目标ViewResultDtoViewDto oldViewInfoResult getView(host, auth, oldViewName, true);if (!oldViewInfoResult.ifSuccess()) {return oldViewInfoResult;}ViewDto newViewInfo new ViewDto();ViewDto oldViewInfo oldViewInfoResult.getData();BeanUtils.copyProperties(oldViewInfo, newViewInfo);newViewInfo.setViewName(newViewName);//2、拷贝目标View内容并重命名ResultDto createResult operation(host, auth, newViewInfo, Operation.CREATE);if (!createResult.ifSuccess()) {return createResult;}ListJobDto jobDtoList oldViewInfo.getJobList();if (CollectionUtils.isEmpty(jobDtoList)) {return createResult;}String[] jobNames new String[jobDtoList.size()];for (int i 0; i jobDtoList.size(); i) {jobNames[i] jobDtoList.get(i).getJobName();}ResultDto addJob2ViewResult Jobs.addJob2View(host, auth, newViewName, jobNames);if (!addJob2ViewResult.ifSuccess()) {return addJob2ViewResult;}if (rename) {//3、再删除旧Viewreturn operation(host, auth, oldViewInfo, Operation.DELETE);} else {return ResultDto.buildSuccessDto();}}/*** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param viewDto ViewDto* param op 操作create-view、update-view、delete-view* return {link ResultDto}*/private static ResultDto operation(String host, String auth, ViewDto viewDto, Operation op) {String operation op.op;String xml ?xml version\1.1\ encoding\UTF-8\?\n hudson.model.ListView\n name viewDto.getViewName() /name\n description viewDto.getDescription() /description\n filterExecutors viewDto.isFilterExecutors() /filterExecutors\n filterQueue viewDto.isFilterQueue() /filterQueue\n properties class\hudson.model.View$PropertyList\/\n jobNames\n comparator class\java.lang.String$CaseInsensitiveComparator\/\n /jobNames\n jobFilters\n /jobFilters\n columns\n hudson.views.StatusColumn/\n hudson.views.WeatherColumn/\n hudson.views.JobColumn/\n hudson.views.LastSuccessColumn/\n hudson.views.LastFailureColumn/\n hudson.views.LastStableColumn/\n hudson.views.LastDurationColumn/\n hudson.views.BuildButtonColumn/\n jenkins.branch.DescriptionColumn /\n /columns\n;if (StringUtils.hasText(viewDto.getIncludeRegex())) {xml includeRegex viewDto.getIncludeRegex() /includeRegex\n;}xml recurse viewDto.isRecurse() /recurse\n /hudson.model.ListView;boolean isUpdateOrDelete Operation.DELETE.equals(op) || Operation.UPDATE.equals(op);String[] finalArgs isUpdateOrDelete ?new String[]{operation, viewDto.getViewName()} : new String[]{operation};CLI cli doWork(host, auth, finalArgs, PROTOCOL_HTTP, xml);int code cli.code;String msg cli.msg;return ResultDto.SUCCESS.equals(String.valueOf(code)) ?ResultDto.buildSuccessDto() : ResultDto.buildErrorDto().msg(msg);}}public static class JenkinsSystem {public enum Operation {/*** 获取Jenkins支持的命令*/HELP(help, 获取Jenkins支持的命令),/*** 获取Jenkins版本信息*/VERSION(version, 获取Jenkins版本信息),/*** 更新Jenkins全局配置信息*/RELOAD_CONFIGURATION(reload-configuration, 更新Jenkins全局配置信息),/*** 重启Jenkins服务*/RESTART(restart, 重启Jenkins服务),/*** 安全重启Jenkins服务Safe Restart Jenkins. Don’t start any builds.*/SAFE_RESTART(safe-restart, 重启Jenkins服务),/*** 停止Jenkins服务*/SHUTDOWN(shutdown, 停止Jenkins服务),/*** 安全停止Jenkins服务Puts Jenkins into the quiet mode, wait for existing builds to be completed,* and then shut down Jenkins.*/SAFE_SHUTDOWN(safe-shutdown, 安全停止Jenkins服务),/*** 清除Jenkins中的构建队列Clears the build queue.*/CLEAR_QUEUE(clear-queue, 清除Jenkins中的构建队列),;SetterGetterprivate String op;SetterGetterprivate String desc;Operation(String op, String desc) {this.setOp(op);this.setDesc(desc);}}/*** 获取Jenkins支持的命令** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* return ResultDto*/public static ResultDto help(String host, String auth) {return operation(host, auth, Operation.HELP);}/*** 获取Jenkins版本信息** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* return ResultDto*/public static ResultDto getVersion(String host, String auth) {return operation(host, auth, Operation.VERSION);}/*** 重启Jenkins服务** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* return ResultDto*/public static ResultDto restart(String host, String auth) {return operation(host, auth, Operation.RESTART);}/*** 安全重启Jenkins服务Safe Restart Jenkins. Don’t start any builds.** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* return ResultDto*/public static ResultDto safeRestart(String host, String auth) {return operation(host, auth, Operation.SAFE_RESTART);}/*** 停止Jenkins服务** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* return ResultDto*/public static ResultDto shutdown(String host, String auth) {return operation(host, auth, Operation.SHUTDOWN);}/*** 安全停止Jenkins服务Puts Jenkins into the quiet mode, wait for existing builds to be completed,* and then shut down Jenkins.** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* return ResultDto*/public static ResultDto safeShutdown(String host, String auth) {return operation(host, auth, Operation.SAFE_SHUTDOWN);}/*** 清除Jenkins中的构建队列Clears the build queue.** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* return ResultDto*/public static ResultDto clearQueue(String host, String auth) {return operation(host, auth, Operation.CLEAR_QUEUE);}/*** 重新加载Jenkins配置信息* Discard all the loaded data in memory and reload everything from file system.* Useful when you modified config files directly on disk.** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* return ResultDto*/public static ResultDto reloadConfiguration(String host, String auth) {return operation(host, auth, Operation.RELOAD_CONFIGURATION);}/*** 基本操作** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param op 操作* return {link ResultDto}*/private static ResultDto operation(String host, String auth, Operation op) {CLI cli doWork(host, auth, new String[]{op.op}, PROTOCOL_HTTP, null);int code cli.code;String msg cli.msg;String successMsg StringUtils.hasText(msg) ? msg.replaceAll(END_SYMBOL, ) : ;return ResultDto.SUCCESS.equals(String.valueOf(code)) ?ResultDto.buildSuccessDto(successMsg) : ResultDto.buildErrorDto().msg(msg);}}/*** 调用Jenkins CLI* 注意查询类时xml为空涉及到使用xml内容创建、更新操作的xml不能为空** param host Jenkins地址比如http://10.100.57.156:8080* param auth Jenkins登录用户名:密码比如admin:admin* param args 请求参数* param protocol 请求协议比如httpwebSocket默认http* param xml 处理XML相关不使用标准输入流此时使用HTTP协议调用* return CLI*/private static CLI doWork(String host, String auth, String[] args, String protocol, String xml) {if (null args || args.length 0) {throw new IllegalArgumentException(args cannot be empty);}if (!StringUtils.hasText(protocol)) {protocol PROTOCOL_HTTP;}byte[] xmlData new byte[]{};if (StringUtils.hasText(xml)) {xmlData xml.getBytes(StandardCharsets.UTF_8);}CLI cli new CLI();String[] baseArgs new String[]{-auth, auth, -s, host, protocol};String[] finalArgs Stream.concat(Arrays.stream(baseArgs), Arrays.stream(args)).toArray(String[]::new);log.info(executing command: {}, JsonUtil.toJSONString(finalArgs));try {cli._main(finalArgs, xmlData);} catch (Exception e) {cli.code -1;cli.msg e.getMessage();log.error(executing command: {} cause error , JsonUtil.toJSONString(finalArgs), e);}return cli;}private static T ResultDtoT doGet(String urlString, String username, String password, Class clz) {URI uri URI.create(urlString);HttpHost host new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());CredentialsProvider credsProvider new BasicCredentialsProvider();credsProvider.setCredentials(new AuthScope(uri.getHost(), uri.getPort()), new UsernamePasswordCredentials(username, password));AuthCache authCache new BasicAuthCache();BasicScheme basicAuth new BasicScheme();authCache.put(host, basicAuth);CloseableHttpClient httpClient HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();HttpGet httpGet new HttpGet(uri);HttpClientContext localContext HttpClientContext.create();localContext.setAuthCache(authCache);if (ObjectUtils.isEmpty(clz)) {clz String.class;}T data (T) new Object();try {CloseableHttpResponse response httpClient.execute(host, httpGet, localContext);String returnMsg EntityUtils.toString(response.getEntity());System.out.println(returnMsg);if (StringUtils.hasText(returnMsg)) {data (T) JsonUtil.string2Obj(returnMsg, clz);return ResultDto.buildSuccessDto().data(data);}return ResultDto.buildSuccessDto().data(returnMsg);} catch (Exception e) {log.error(call {} failed, urlString, e);return ResultDto.buildErrorDto().data(data);}}
}