jenkins中集成commander应用
jenkins
集成测试
promotion
最近参加公司的集成测试平台的开发,在开发中遇到了不少问题,两个星期的迭代也即将完成,在这也用这篇博客记录下开发中的问题,供读者参考
公司的应用较多,所以需要了解这几种应用在jenkins中如何做构建,我自己参与的有两种commander的应用,一种是大数据类的,一个是我们服务端架构组的scala应用
1、大数据应用BigData
配置如下:
配置文件对应的xml文件:通过crul获取xml配置文件:http://host/job/tar_py_dwx_dev/config.xml
<project> <actions/> <description/> <keepDependencies>falsekeepDependencies> <properties> <com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty plugin="[email protected]"> <gitLabConnection/> com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty> <hudson.plugins.promoted__builds.JobPropertyImpl plugin="[email protected]"> <activeProcessNames> <string>Deploy DEVstring> activeProcessNames> hudson.plugins.promoted__builds.JobPropertyImpl> properties> <scm class="hudson.plugins.git.GitSCM" plugin="[email protected]"> <configVersion>2configVersion> <userRemoteConfigs> <hudson.plugins.git.UserRemoteConfig> <url>ssh://[email protected]:10022/bigdata/dwx.giturl> <credentialsId>84f4be19-ea8d-4271-8cfb-42af8f507285credentialsId> hudson.plugins.git.UserRemoteConfig> userRemoteConfigs> <branches> <hudson.plugins.git.BranchSpec> <name>*/developname> hudson.plugins.git.BranchSpec> branches> <doGenerateSubmoduleConfigurations>falsedoGenerateSubmoduleConfigurations> <submoduleCfg class="list"/> <extensions/> scm> <assignedNode>!macminiassignedNode> <canRoam>falsecanRoam> <disabled>falsedisabled> <blockBuildWhenDownstreamBuilding>falseblockBuildWhenDownstreamBuilding> <blockBuildWhenUpstreamBuilding>falseblockBuildWhenUpstreamBuilding> <triggers> <hudson.triggers.SCMTrigger> <spec>H/5 * * * *spec> <ignorePostCommitHooks>falseignorePostCommitHooks> hudson.triggers.SCMTrigger> triggers> <concurrentBuild>falseconcurrentBuild> <builders> <hudson.tasks.Shell> <command> project=dwx1 cd ${WORKSPACE} tar zcvf ${project}.tar.gz * aws s3 cp ${project}.tar.gz s3://lattebank-jenkins-build-dev/${JOB_BASE_NAME}/${BUILD_NUMBER}/ --region cn-north-1 rm -rf ${project}.tar.gz command> hudson.tasks.Shell> builders> <publishers/> <buildWrappers/> project>
从xml中获取的信息有点和图中的配置文件有点对应不上
对于promotion的脚本在xml配置文件中是无法获取的,这时候就有一个问题,这种api是无法获取到promotion的的脚本,同时这也给我们的工作带来了极大的挑战,那也意味着单纯的通过这种方法是无法实现commander应用的部署,和通过平台的方式去直接操作jenkins的配置
但经过查询相关的api并不能找到相关的内容,经过不懈的努力,终于找到了和promote build 插件相关的api
查询:http://host/job/jobName/promotion/process/promotionName/config.xml
这个接口能获取到它的xml文件,但是并不能对该配置文件进行增加和修改
对此我自己封装了一些方法:
/** * @author chenlang * date 2018/5/7 */ @Slf4j public class JenkinsPromotionUtils { private static final String SUB_PATH_PROMOTION_COOMMAND = "/hudson.plugins.promoted__builds.PromotionProcess"; private static final String SUB_PATH_BUILD = "/buildSteps"; private static final String SUB_PATH_BUILDER_SHELL_COMMAND = "/hudson.tasks.Shell/command"; private static final String PATH_PROMOTION_COMMAND = SUB_PATH_PROMOTION_COOMMAND + SUB_PATH_BUILD + SUB_PATH_BUILDER_SHELL_COMMAND; private static String CREATE_PROMOTION_JSON = "{'properties':{'stapler-class-bag':'true','hudson-plugins-promoted_builds-JobPropertyImpl':{'promotions':{'activeItems':{'name':'%s','isVisible':'','icon':'star-gold','hasAssignedLabel':false,'assignedLabelString':'','conditions':{'stapler-class-bag':'true'}}}}}}"; private static final String CONTENT_TYPE = "application/x-www-form-urlencoded"; public static void updatePromotionShell(Document jobConfigDocument, String jobName, JenkinsPromotionClient jenkinsPromotionClient, String promotionShell, String path) throws IOException, DocumentException { if (StringUtils.isBlank(promotionShell)) { return; } String promotionName = getPromotionName(jobConfigDocument, path); Document document = jenkinsPromotionClient.getJobPromotionXml(jobName, promotionName); document.selectSingleNode(PATH_PROMOTION_COMMAND).setText(promotionShell); jenkinsPromotionClient.updateJob(jobName, promotionName, document.asXML()); } public static void createPromotionShell(Document jobConfigDocument, String tmpJobName, String jobName, String promotionShell, String path, JenkinsPromotionClient jenkinsPromotionClient) throws IOException, DocumentException { if (StringUtils.isBlank(promotionShell)) { return; } String promotionName = getPromotionName(jobConfigDocument, path); Document document = jenkinsPromotionClient.getJobPromotionXml(tmpJobName, promotionName); document.selectSingleNode(PATH_PROMOTION_COMMAND).setText(promotionShell); Mapmap = Maps.newHashMap(); map.put("Content-Type", CONTENT_TYPE); map.put("json", String.format(CREATE_PROMOTION_JSON, promotionName)); try { jenkinsPromotionClient.createJob(jobName, map); } catch (Exception e) { log.error("初创promotion时失败" + e); } jenkinsPromotionClient.createJob(jobName, promotionName, document.asXML()); } public static String getPromotionName(Document jobConfigDocument, String path) { return jobConfigDocument.selectSingleNode(path).getText(); } }
package cn.caijiajia.phoenix.service.jenkins; import com.offbytwo.jenkins.client.JenkinsHttpClient; import com.offbytwo.jenkins.client.util.EncodingUtils; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.IOException; import java.util.Map; /** * @author chenlang * date 2018/5/4 */ @Component public class JenkinsPromotionClient { @Autowired private JenkinsHttpClient jenkinsHttpClient; public JenkinsPromotionClient() { } /** * 获取job的promotion配置文件 * * @param jobName job名称 * @param promotionName promotion名称 * @return * @throws IOException */ public Document getJobPromotionXml(String jobName, String promotionName) throws IOException, DocumentException { return DocumentHelper.parseText(this.getJobXml(jobName, promotionName)); } /** * 更新job * * @param jobName * @param promotionName * @param jobXml * @throws IOException */ public void updateJob(String jobName, String promotionName, String jobXml) throws IOException { this.jenkinsHttpClient.post_xml(this.toJobBaseUrl(jobName, promotionName) + "/config.xml", jobXml, true); } /** * 添加job脚本 * * @param jobName * @param jobXml * @throws IOException */ public void createJob(String jobName, String promotionName, String jobXml) throws IOException { this.jenkinsHttpClient.post_xml(this.toJobBaseUrl(jobName, promotionName) + "/config.xml", jobXml, true); } /** * 添加promotion的job * * @param jobName * @param map * @throws IOException */ public void createJob(String jobName, Map map) throws IOException { this.jenkinsHttpClient.post_form("/job/" + EncodingUtils.encode(jobName) + "/configSubmit?", map, false); } private String getJobXml(String jobName, String promotionName) throws IOException { return this.jenkinsHttpClient.get(this.toJobBaseUrl(jobName, promotionName) + "/config.xml"); } private String toJobBaseUrl(String jobName, String promotionName) { return "/job/" + EncodingUtils.encode(jobName) + "/promotion/process/" + promotionName; } /** * promotion脚本的构建 * @param jobName * @param promotionName * @param version * @param isFirstBuild * @throws IOException */ public void build(String jobName,String promotionName,Integer version,boolean isFirstBuild) throws IOException{ if (isFirstBuild) { this.jenkinsHttpClient.post("/job/"+ EncodingUtils.encode(jobName) + "/"+version+"/promotion/forcePromotion?name="+promotionName+"&json=%7B%7D&Submit=Force promotion"); } else { this.jenkinsHttpClient.post("/job/"+ EncodingUtils.encode(jobName) + "/"+version+"/promotion/"+promotionName+"/build?json=%7B%7D&Submit=Re-execute promotion"); } } }
其中的方法封装了对promote build插件中关于配置的增删改查,以及promotion脚本的构建