小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

持續(xù)集成JenkinsAPI常見用法

 bananarlily 2015-09-19
摘要 jenkins(持續(xù)集成開源工具)提供了豐富的api接口,基本上所有的操作都可以使用curl來從后臺調(diào)度,包括:創(chuàng)建項目,禁用項目,啟用項目,獲取項目描述,獲取配置文件,普通觸發(fā),scm觸發(fā),帶參數(shù)觸發(fā),帶補丁觸發(fā)。同時也可以使用python 庫 jenkinsapi https://pypi./pypi/jenkinsapi

【背景】:部門在搞持續(xù)集成,使用jenkins作為核心調(diào)度,要再其基礎(chǔ)上進(jìn)行二次封裝,所以需要研究下jenkins的api。筆者主要負(fù)責(zé)搭建平臺,在研究用法也花費了些時間,本文主要做個簡要的記錄,希望能為各位朋友節(jié)省時間。

【環(huán)境】:(默認(rèn)讀者已經(jīng)具備了基本的持續(xù)集成經(jīng)驗和jenkins用法

1. Jenkins1.455 

2. 系統(tǒng)Suse

3. Tomcat 6.0.37

4. Java 1.6.0_26

5. patch-parameter 

【API介紹】

 Jenkins提供了html、json、python API,實質(zhì)都是以http get/post方式調(diào)用的。查看http://www./jenkins/api/ 即可得到相應(yīng)的說明,如圖:

 

【API實踐】

1.創(chuàng)建

curl -X POST http://www./jenkins/createItem?name=JavaStd  --user peterguo:peterguo --data-binary "@javastd.config.xml" -H "Content-Type: text/xml"

2.禁用 

curl -X POST http://www./jenkins/job/JavaStd/disable  --user peterguo:peterguo

3.啟用 

curl -X POST http://www./jenkins/job/JavaStd/enable --user peterguo:peterguo

4.刪除 

curl -X POST http://www./jenkins/job/JavaStd/doDelete --user peterguo:peterguo

5.獲取項目描述 

curl -X GET http://www./jenkins/job/JavaStd/description --user peterguo:peterguo

6.獲取配置文件 

curl -X GET http://www./jenkins/job/JavaStd/config.xml --user peterguo:peterguo

7.觸發(fā)SCM檢查 

curl -X GET http://www./jenkins/job/JavaStd/polling --user peterguo:peterguo

8.普通觸發(fā) 

curl -X GET http://www./jenkins/job/JavaStd/build --user peterguo:peterguo

9.帶參數(shù)觸發(fā)

curl -X GET "http://www./jenkins/job/helloworld-freestyle/buildWithParameters?bAllTest=&Choices=2&strParam=abc" --user peterguo:peterguo

10.帶文件觸發(fā)

curl  -X POST "http://localhost:8080/job/Demo/buildWithParameters?assertMethod=online" -F "input=@atest.txt"

11.參數(shù)和補丁觸發(fā)  

curl -X POST "http://www./jenkins/job/helloworld-freestyle/buildWithParameters?bAllTest=&Choices=2&strParam=abc" --user peterguo:peterguo -F "action=upload" -F "patch.diff=@OtherTest.java.patch"

注:帶補丁觸發(fā)需要先安裝補丁插件,并設(shè)置項目的補丁參數(shù)

【通過Python-curl庫調(diào)用】

 提供python使用pycurl調(diào)用的例子片段,實際和curl調(diào)用一樣,優(yōu)點是易整合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import pycurl
url = "http://10.129.145.112:8081/jenkins/job/helloworld-freestyle/config.xml"
crl = pycurl.Curl()
crl.setopt(pycurl.VERBOSE,1)
crl.setopt(pycurl.FOLLOWLOCATION, 1)
crl.setopt(pycurl.MAXREDIRS, 5)
crl.setopt(pycurl.USERPWD, "peterguo:peterguo")
  
crl.setopt(pycurl.CONNECTTIMEOUT, 60)
crl.setopt(pycurl.TIMEOUT, 300)
crl.setopt(pycurl.HTTPPROXYTUNNEL,1)
crl.fp = StringIO.StringIO()
crl.setopt(pycurl.URL, url)
crl.setopt(crl.WRITEFUNCTION, crl.fp.write)
crl.perform()
ret = crl.fp.getvalue()

【通過Python-jenkinsapi庫調(diào)用】

   這里給出代碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
from jenkinsapi.jenkins import Jenkins
class CJenkinsAPI():  
    '''
    均采用同步設(shè)置超時機制
    創(chuàng)建項目:輸入:configid planid         
    創(chuàng)建任務(wù):輸入:configid planid   返回:返回碼 msg buildid  額外動作:不寫SQL
    查詢?nèi)蝿?wù):輸入:configid planid taskid  返回:返回碼 msg buildid  額外動作:結(jié)束更新SQL(包括成功或失?。?,未結(jié)束則不處理
    終止任務(wù):輸入:configid planid taskid  返回:返回碼 msg buildid  額外動作:終止成功寫SQL
    '''
    __doc__ = '''Usage: \t\tCJenkinsAPI.createProject\t\tCJenkinsAPI.triggerBuild\t\t'''
    _strConfigTemplatePath = ""
    _strConfigDataPath = ""
    def __init__(self):
        import pycurl 
        pass
         
    def __del__(self):
        pass
    @staticmethod
    def createProject(nPlanId, strConfigId):
        '''
        Return:返回碼/返回信息
        先根據(jù)配置文件生成項目
        '''
        #用于測試
        nPlanId = 14 
        strConfigId = "D1057406"    
         
        #返回
        nRet, strMsg, nBuild = 0, "", 0
         
        #配置文件模版
        strConfigTemplate = CJenkinsAPI._strConfigTemplatePath + "/config.template.xml"        
        #用planID和配置ID作為項目名
        strProjectName = "P%d-%s" % (nPlanId, strConfigId ) 
         
        #訪問數(shù)據(jù)庫拿到構(gòu)建節(jié)點IP和SVN
        strBuildNodeIP = ""
        strProjectSVN = ""
         
        oProxy = CSqlProxy("10.129.145.112""ci_test""ci_test""ci_plat")
        #SVN從t_build_plan中取
        lSelectRet = CSqlProxy.selectFromTable(oProxy.m_oCon, "t_build_plan", ["f_svn"], " where f_plan_id='%d' " % nPlanId)
        strProjectSVN = lSelectRet[0]["f_svn"]
        #配置信息從t_ci_config中取
        lSelectRet = CSqlProxy.selectFromTable(oProxy.m_oCon, "t_ci_config", ["f_node_ip""f_run_param"], " where f_config_id='%s' " % strConfigId)
        strBuildNodeIP = lSelectRet[0]["f_node_ip"]
        strRunParam = lSelectRet[0]["f_run_param"]
        oProxy.close()
         
        strNodeFlag = {True:"", False:"slave_"}["10.129.145.112in strBuildNodeIP]
        dReplaceInfo = {"PROJ_DESC"     "This is generate by Ci-plat, with plan_id[%d] and config_id[%s]" % (nPlanId, strConfigId),\
                        "SVN_URL"       : strProjectSVN.replace("http://tc-svn.tencent.com""svn://172.27.198.49:8081"),\
                        "BUILD_NODE_IP" : strNodeFlag + strBuildNodeIP,\
                        "BUILD_SCRIPT"  '''sh build.sh %s ''' % strRunParam, \
                        "JUNIT_TEST_PATH"   :"target/surefire-reports/*.xml", \
                        "COVERAGE_PATH" :"target/site/cobertura/", \
                        }
        #利用模版生成配置文件
        oConf = CCiConfig(strConfigTemplate, dReplaceInfo)
        strCurConfigXml = CJenkinsAPI._strConfigDataPath + "/" + strProjectName + ".config.xml"
        oConf.dump2file(strCurConfigXml)
         
        strCommand = 'curl -X POST http://10.129.145.112:8081/jenkins/createItem?name=%s --user peterguo:peterguo --data-binary "@%s" -H "Content-Type: text/xml"' % (strProjectName, strCurConfigXml)
        nRet = os.system(strCommand)
        strMsg = {True:"SucceedCreate,Url:"False:"FailedCreate,Url:"}[nRet==0]
        print "%d|%s|%d" % (nRet, tran2UTF8(strMsg)+"[http://10.129.145.112:8081/jenkins/job/%s]" % strProjectName, nBuild)
         
    @staticmethod    
    def triggerBuild(nPlanId, strConfigId):
        '''
        Return:
        觸發(fā)前先更新配置文件,使用遠(yuǎn)程腳本
        觸發(fā)前獲取要出發(fā)的編號
        '''
        #返回
        nRet, strMsg, nBuild = 0, "", 0
         
        #配置文件模版
        strConfigTemplate = CJenkinsAPI._strConfigTemplatePath + "/config.template.xml"  
        #用planID和配置ID作為項目名
        strProjectName = "P%d-%s" % (nPlanId, strConfigId ) 
         
        #訪問數(shù)據(jù)庫拿到構(gòu)建節(jié)點IP和SVN
        strBuildNodeIP = ""
        strProjectSVN = ""
         
        oProxy = CSqlProxy("10.129.145.112""ci_test""ci_test""ci_plat")
        #SVN從t_build_plan中取
        lSelectRet = CSqlProxy.selectFromTable(oProxy.m_oCon, "t_build_plan", ["f_svn"], " where f_plan_id='%d' " % nPlanId)
        strProjectSVN = lSelectRet[0]["f_svn"]
        #配置信息從t_ci_config中取
        lSelectRet = CSqlProxy.selectFromTable(oProxy.m_oCon, "t_ci_config", ["f_node_ip""f_run_param"], " where f_config_id='%s' " % strConfigId)
        strBuildNodeIP = lSelectRet[0]["f_node_ip"]
        strRunParam = lSelectRet[0]["f_run_param"]
        oProxy.close()
         
        strNodeFlag = {True:"", False:"slave_"}["10.129.145.112in strBuildNodeIP]
        dReplaceInfo = {"PROJ_DESC"     "This is generate by Ci-plat, with plan_id[%d] and config_id[%s]" % (nPlanId, strConfigId),\
                        "SVN_URL"       : strProjectSVN.replace("http://tc-svn.tencent.com""svn://172.27.198.49:8081"),\
                        "BUILD_NODE_IP" : strNodeFlag + strBuildNodeIP,\
                        "BUILD_SCRIPT"  '''sh build.sh %s ''' % strRunParam, \
                        "JUNIT_TEST_PATH"   :"target/surefire-reports/*.xml", \
                        "COVERAGE_PATH" :"target/site/cobertura/", \
                        }
        #利用模版生成配置文件
        oConf = CCiConfig(strConfigTemplate, dReplaceInfo)
        strCurConfigXml = CJenkinsAPI._strConfigDataPath + "/" + strProjectName + ".config.xml"
        oConf.dump2file(strCurConfigXml)
         
        #更新配置文件
        strCommand = 'curl -X POST http://10.129.145.112:8081/jenkins/job/%s/config.xml --user peterguo:peterguo --data-binary "@%s" -H "Content-Type: text/xml"' % (strProjectName, strCurConfigXml)
        nRet = os.system(strCommand)
        strMsg += {True:"更新配置成功"False:"更新配置失敗"}[nRet==0]
         
        #獲取下一次構(gòu)建編號
        nBuild = Jenkins("http://10.129.145.112:8081/jenkins","peterguo","peterguo")[strProjectName.encode("utf8")].get_next_build_number()
         
        #觸發(fā)構(gòu)建
        strCommand = 'curl -X POST http://10.129.145.112:8081/jenkins/job/%s/build --user peterguo:peterguo ' % (strProjectName)
        nRet = os.system(strCommand)
        strMsg = {True:"SucceedTrigger,Url:"False:"FailedTrigger,Url:"}[nRet==0]
        print "%d|%s|%d" % (nRet, tran2UTF8(strMsg)+"[http://10.129.145.112:8081/jenkins/job/%s/%d]" % (strProjectName, nBuild), nBuild )
         
    @staticmethod
    def infoBuild(nPlanId, strConfigId, nTaskId):
        '''
        Return:
        '''
        strProjectName = "P%d-%s" % (nPlanId, strConfigId ) 
        oProxy = CSqlProxy("10.129.145.112""ci_test""ci_test""ci_plat")
        strWhere = " where f_task_id='%d' " % int(nTaskId)
        lSelectRet = CSqlProxy.selectFromTable(oProxy.m_oCon, "t_build_task", ["f_build_id"], strWhere)
        oProxy.close()
        nBuildId = int(lSelectRet[0]["f_build_id"])
        oCurBuild = Jenkins("http://10.129.145.112:8081/jenkins","peterguo","peterguo")[strProjectName.encode("utf8")].get_build(nBuildId)
        bRunning = oCurBuild.is_running()
        if bRunning == True:
            print "1|Running|%d" % nBuildId 
            return
        #最重要更新的數(shù)據(jù)
        dResult2Sql = {}
         
        #取測試用例結(jié)果的個數(shù)信息
        if oCurBuild.has_resultset():
            dResult = oCurBuild.get_actions()
        else:
            dResult = {"failCount":0"totalCount":0"skipCount":0
        oDeltaDur = oCurBuild.get_duration()
        oBuildBegin = utc2LocalDatetime(oCurBuild.get_timestamp())
        oBuildEnd = oBuildBegin + oDeltaDur
        dResult2Sql["f_case_fail"= dResult['failCount']
        dResult2Sql["f_case_total"= dResult['totalCount']
        dResult2Sql["f_case_skip"= dResult['skipCount']
        dResult2Sql["f_build_duration"= "%.3f" % (oDeltaDur.days * 24 * 60 + oDeltaDur.seconds / 60.0)
        dResult2Sql["f_build_url"= oCurBuild.baseurl
        dResult2Sql["f_build_result"= {True:0False:1}[oCurBuild.is_good()]
        dResult2Sql["f_task_status"= TASK_DONE
        dResult2Sql["f_build_time"= oBuildBegin.strftime("%Y-%m-%d %H:%M:%S")
        dResult2Sql["f_build_end"= oBuildEnd.strftime("%Y-%m-%d %H:%M:%S")
        dResult2Sql["f_msg_info"= tran2GBK("任務(wù)完成,收集數(shù)據(jù)完成")
         
        #任務(wù)已經(jīng)完成,需要入庫相關(guān)數(shù)據(jù),更新相關(guān)狀態(tài)
        oProxy = CSqlProxy("10.129.145.112""ci_test""ci_test""ci_plat")
        strWhere = " where f_task_id='%d' " % int(nTaskId)
        CSqlProxy.updateValueToDBTable(oProxy.m_oCon, "t_build_task", dResult2Sql.keys(), dResult2Sql.values(), strWhere)
        oProxy.close()
        #for item in dResult2Sql.items():
        #    print item[0], str(item[1])
        print "%d|%s|%d" % (0"SucceedUpdated", nBuildId)
         
    @staticmethod    
    def stopBuild(nPlanId, strConfigId, nTaskId):
        '''
        Return:
        '''
        strProjectName = "P%d-%s" % (nPlanId, strConfigId ) 
        oProxy = CSqlProxy("10.129.145.112""ci_test""ci_test""ci_plat")
        strWhere = " where f_task_id='%d' " % int(nTaskId)
        lSelectRet = CSqlProxy.selectFromTable(oProxy.m_oCon, "t_build_task", ["f_build_id"], strWhere)
        oProxy.close()
        nBuildId = int(lSelectRet[0]["f_build_id"])
         
        oCurBuild = Jenkins("http://10.129.145.112:8081/jenkins","peterguo","peterguo")[strProjectName.encode("utf8")].get_build(nBuildId)
        bRunning = oCurBuild.is_running()
        if bRunning == False:
            print "2|AlreadyStopped|%d" % nBuildId
            return
        #觸發(fā)停止命令
        oCurBuild.stop()
                 
        #等停止
        oCurBuild.block_until_complete()
         
        #最重要更新的數(shù)據(jù)
        dResult2Sql = {}
         
        #取測試用例結(jié)果的個數(shù)信息
        if oCurBuild.has_resultset():
            dResult = oCurBuild.get_actions()
        else:
            dResult = {"failCount":0"totalCount":0"skipCount":0
        oDeltaDur = oCurBuild.get_duration()
        oBuildBegin = utc2LocalDatetime(oCurBuild.get_timestamp())
        oBuildEnd = oBuildBegin + oDeltaDur
        dResult2Sql["f_case_fail"= dResult['failCount']
        dResult2Sql["f_case_total"= dResult['totalCount']
        dResult2Sql["f_case_skip"= dResult['skipCount']
        dResult2Sql["f_build_duration"= "%.3f" % (oDeltaDur.days * 24 * 60 + oDeltaDur.seconds / 60.0)
        dResult2Sql["f_build_url"= oCurBuild.baseurl
        dResult2Sql["f_build_result"= {True:0False:1}[oCurBuild.is_good()]
        dResult2Sql["f_task_status"= TASK_ABORTED
        dResult2Sql["f_build_time"= oBuildBegin.strftime("%Y-%m-%d %H:%M:%S")
        dResult2Sql["f_build_end"= oBuildEnd.strftime("%Y-%m-%d %H:%M:%S")
        dResult2Sql["f_msg_info"= tran2GBK("TaskStopped")
         
        #任務(wù)已經(jīng)完成,需要入庫相關(guān)數(shù)據(jù),更新相關(guān)狀態(tài)
        oProxy = CSqlProxy("10.129.145.112""ci_test""ci_test""ci_plat")
        strWhere = " where f_task_id='%d' " % int(nTaskId)
        CSqlProxy.updateValueToDBTable(oProxy.m_oCon, "t_build_task", dResult2Sql.keys(), dResult2Sql.values(), strWhere)
        oProxy.close()
        #for item in dResult2Sql.items():
        #    print item[0], str(item[1])
        print "%d|%s|%d" % (1, tran2UTF8("SucceedStopped"), nBuildId)
    @staticmethod    
    def deleteProject(nPlanId, strConfigId):        
       '''
       Return:返回碼/返回信息 curl -X POST http://10.129.145.112:8081/jenkins/job/JavaStd/doDelete --user peterguo:peterguo
       '''    
       strProjectName = "P%d-%s" % (nPlanId, strConfigId ) 
       strCommand = 'curl -X POST http://10.129.145.112:8081/jenkins/job/%s/doDelete --user peterguo:peterguo' % (strProjectName)
       CColorPrint.colorPrintStr("CMD:[%s]" % strCommand, "green")
       nRet = os.system(strCommand)
       strMsg = {True:"SucceedDeleted"False:"FailedDeleted"}[nRet==0]
       print nRet, tran2UTF8(strMsg), 0

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多