歡迎您光臨本站 註冊首頁

基於Python的Jenkins的二次開發操作

←手機掃碼閱讀     techdo @ 2020-05-13 , reply:0

背景
最近我們在整一個雲執行的平臺,底層用的是Jenkins來做執行引擎,方便的把我們的腳本做一個統一的調度。
Jenkins確實是一個非常方便的框架,它提供了一整套的RESTful的API,可以非常方便的做二次開發,而且提供了一個python的庫,操作起來就更加方便了。
常用的Jenkins概念
我們在使用Jenkins的時候,一般看到的都是Jenkins的View。
也就是說我們看到的基本上都是一些視圖。
每一個構建的內容,無論是執行用例,跑腳本,還是打包編譯發佈,都是一個job。
每一個job都有一個對應的name,如果這個job被放在某個文件夾了,那麼name就是文件夾名+job名。在查看job信息的時候,會返回一個full_name字段,指的就是這個了。
PythonSDK
pip install python-jenkins執行這條命令就可以安裝SDK了。
官網:https://pypi.org/project/python-jenkins/
說明文檔:http://python-jenkins.readthedocs.io/en/latest/
說明文檔都是英文的,如果有興趣,看這塊當然最好,不過這個SDK實際上非常非常的簡單,如果直接去看源代碼,也是沒問題的,我在開發的過程中,基本上都是去看源碼來寫的,SDK裡面函數命名比較直白,不用深刻理解也能夠正常的去使用。
這裡列一些比較常用的方法,也是我這次開發的時候用到的一些,我按照我自己寫的過程中,一步一步的寫出來。
開發過程
job信息查詢
在Jenkins中,每一個構建都是一個job,所以,我們做開發的時候,要在頁面上展示歷史的構建信息,因此,要能夠拿到歷史執行job的信息。因此我們要使用get_job_info這個方法。
def get_job_info(self, name, depth=0, fetch_all_builds=False): '''Get job information dictionary. :param name: Job name, ``str`` :param depth: JSON depth, ``int`` :param fetch_all_builds: If true, all builds will be retrieved from Jenkins. Otherwise, Jenkins will only return the most recent 100 builds. This comes at the expense of an additional API call which may return significant amounts of data. ``bool`` :returns: dictionary of job information '''
這裡的name參數指的是job的名字,比如我新建了一個叫自動化測試這麼個job,那麼這個name傳的就是自動化測試,如果我把這個job放到了某個文件夾中,那麼name這個參數需要傳文件夾名/自動化測試。
這裡有一個坑,在Python2.7版本中傳遞這個name,如果以變量的形式傳遞過去,會有一個報錯,規避的方法是name.encode('utf-8')做一下編碼的處理。返回的參數是這些:
在builds字段裡面就存有所有的歷史構建數據。在property這個字段中放有Jenkins構建時的各種參數。
構建日誌
拿到了構建數據,我們需要在頁面上展示出來,如果能在頁面上直接看日誌就更方便了,因此要把每次的構建日誌拿出來,需要調用get_build_console_output這個方法。
def get_build_console_output(self, name, number): '''Get build console text. :param name: Job name, ``str`` :param number: Build number, ``int`` :returns: Build console output, ``str`` '''
這裡可以拿到Jenkins的構建日誌,返回的就是一個字符串了。需要注意的是,如果你想要構建的時候也展示構建日誌,只需要在構建的時候調用這個方法就行,會返回調用時候構建的日誌,用socket或者輪詢的方式都可以實現實時日誌的展示。
執行構建
執行構建當然是非常關鍵的一步,我們可以使用build_job這個方法來執行構建。
def build_job(self, name, parameters=None, token=None): '''Trigger build job. This method returns a queue item number that you can pass to :meth:`Jenkins.get_queue_item`. Note that this queue number is only valid for about five minutes after the job completes, so you should get/poll the queue information as soon as possible to determine the job's URL. :param name: name of job :param parameters: parameters for job, or ``None``, ``dict`` :param token: Jenkins API token :returns: ``int`` queue item '''
這裡的name參數跟job信息查詢的參數一樣,也會有編碼的問題。parameters字段傳入的是一個字典類型,也就是在頁面上點擊構建的時候,需要填入的參數。token參數在Jenkins這個類初始化的時候就已經有了,所以一般來說無需傳入。這個方法會返回一個queue_item的編號,這個就是Jenkins的構建編號,這個編號可以做一些其他數據的查詢,比如構建狀態,取消構建等操作,在SDK裡面都有對應的方法。
注意:絕對不行用這個來查詢是否處於構建中,這個編號在一定時間內會出現失效的情況,如果構建時間過長,會導致查詢不到結果而報錯,實際上job依然處於構建中
這些方法使用起來比較方便,但是有一些侷限性,我們如果在構建的時候用了第三方插件,這些方法是沒辦法拿到第三方插件的結果的,比如我們這裡用RobotFramework的插件來處理了結果,用這些方法是沒辦法拿到結果的。
從原理入手
Jenkins對外提供的是一個RESTful的接口,那麼Python的SDK做的動作實際上就是去請求這個接口,只不過做了一些包裝,保證了易用性,很多方法的核心,都會用到jenkins_request,比如:
response = self.jenkins_request(requests.Request(
'POST', self.build_job_url(name, parameters, token)))
有興趣的可以自己去讀一讀源碼,整個SDK實際上就是基於requests這個庫做了一下包裝,然後最終都是通過jenkins_request去請求RESTful的API。我們進入jenkins的頁面,在右下角能看到一個這樣的東西。
有這個標記的頁面,就是有接口的,那麼這個接口是怎麼拿的呢?
從源碼裡面可以找到答案,很多方法裡面都有這麼樣一個東西。
self.jenkins_open(requests.Request('GET', self._build_url(INFO),auth=auth), add_crumb=False, resolve_auth=False) response = self.jenkins_open(requests.Request('GET', self._build_url(BUILD_INFO,locals())))
在最上方的配置中可以找到:
INFO = 'api/json'
也就是說,在我們看到頁面的後方加上/api/json就可以拿到數據了。
所有的操作都在這個數據的背後了,也就是說只要寫好這個url的拼接規則,就能很簡單的去做二次開發了。
當然,在開發的過程中,也是有很多坑的,比如拿歷史數據的時候,接口竟然不返回歷史構建的狀態。。。。
總結
整個開發過程下來還算比較順利,由於源碼比較簡單的原因,基本上遇到問題都能通過看源碼來解決,但是比較大的問題就是返回結果的枚舉沒有一個地方列出來,所以導致開發完成後經常有地方需要修修補補。


[techdo ] 基於Python的Jenkins的二次開發操作已經有398次圍觀

http://coctec.com/docs/python/shhow-post-234274.html