Jenkins: 使用groovy + job-dsl 創建並觸發job


Jenkins: 使用groovy + job-dsl 創建並觸發job

背景:

我們的 Automation 測試腳本需要在10個不同語言的機器上跑,本地化測試產品。
我們用Jenkins啟動測試執行,需要同時向1-10個機器發送文件和腳本運行命令,現有Jenkins的配置采用master/slave 機制如下:

Dispatcher Job:

1。 啟用參數化,每個語言機器傳遞兩個參數:

- Choice Parameter: slave Node 名,比如這里的NodeLabel1,表示第一台目標機器

Node Name

- File Parameter: 要發送給目標機器的文件

File Name

2。 在Build Steps中trigger seed job:

Seed Job: 設置具體的運行腳本。

現有設計的問題:

運行很流暢,但是維護不方便

  • 每個Slave Node都添加一個Choice Paramter 和 File Parameter,
  • Build Step中也要添加10次trigger seed job,
  • Steps中如有一處腳本改動,需重復改動10次
  • 如果有新添加測試機器,需要在Parameters中手動添加新Node, 在Steps中也要添加。

改進需求:

自動獲取所有Node列表,減少不必要的手動增添Node。

在Build Steps中,通過腳本trigger seed job,這樣避免重復設置10次trigger step, 提高可重復性(Reusability)。

改進方案:

使用Groovy腳本,安裝Jenkins插件:

  • Active Choices: 一個蠻好的參數化插件,可插入Groovy腳本和文件(集成Scriptlet插件)。

  • Scriptler:Groovy腳本插件,可以集中管理腳本文件。

  • Job-DSL: 一個很好的利用DSL設置和運行Job的插件。

具體實施:

准備global scripts,獲取全部節點,用的是scriptler插件。

1。 在Jenkins->Scriptler中創建getAllNodeByProject.groovy文件,用來獲取所有的Node機器。需要的話也可以加入一些篩選條件,比如在線與否。

scriptler中支持參數傳遞,這里的project就是預先設置的參數,可在job調用該腳本時進行設置。


	def list = jenkins.model.Jenkins.instance.slaves.findAll{
	  if (it.name.contains(project)) it.name
	}.collect{it.name}
	list.add(0,"None")
	return list

2。 在Jenkins->Scriptler中創建getRuntimeNodes.groovy文件,用來獲取dispatcher job在運行時指定的Node機器。


				import hudson.model.*
                def list =""
                def runable=false
                def build = Thread.currentThread()?.executable
                // get the selected node parameter value at runtime
                def nodes = build?.actions.find { it instanceof ParametersAction }?.parameters.collect{
                    (it instanceof StringParameterValue)?it.value:""
                } as List
                println "node is $nodes"
                nodes.unique().removeAll(["None"])
                nodes.remove(" ")
				nodes.remove("")
                if (nodes!=[]) {
                    list=nodes.join(",").toString()
                }
                println "list is:  $list"
                if (list!=" " && list!="") runable=true
                println "runable is $runable"
                build.addAction( new ParametersAction([new StringParameterValue("runtimeNodes",list)]))
                build.addAction( new ParametersAction([new BooleanParameterValue("runable",runable)]))

運行結果是,在dispatcher job runtime會新建兩個參數:

  • String參數 runtimeNodes: 存放運行時獲取用戶指定的Node 機器列表,用於后續在這些node 機器上分別trigger seed job

  • 布爾型參數 runable:如果沒有指定任何Node,則將runable設為false, 即不會trigger seed job

創建main,dispatcher和seed jobs

手動創建一個名為main的 job, 用來動態生成dispatcher and seed jobs.

在main中用job-dsl創建dispatcher job

在main job中,插入一個Process Job DSLs 構建步驟, 下面的代碼會在運行時創建一個名為dispatcher的job:

  • 為每個language node (“Client_CHS","Client_JPN") 設置了active choice node 參數和File參數。
  • 創建一個conditional step, 如果符合條件,則trigger seed job,並將用戶運行時指定的所有node以NodeListFactory參數方式傳給seed job。

				import hudson.model.*

				// get all available nodes if its name contains "client" - specific for our project use;
                def nodes = hudson.model.Hudson.instance.slaves.findAll{
                    if (it.name.contains("Client")) it.name
                }.collect{it.name}
                nodes.add(0,"None")

				//def nodes = ["Client_JPN","Client_CHS"]

                defineJob(nodes-["None"],"dispatcher") // setup the dispatcher job

                // method to define a dispatcher job
                def defineJob(nodes,jobName) {
                    return job(jobName) {
                        def list =[]
                        nodes.each {
                            def node =it
                            parameters {
                                activeChoiceParam(node) {
                                    description('Allows user choose from choices')
                                    filterable()
                                    choiceType('SINGLE_SELECT')
                                    scriptlerScript('getAllNodesByProject.groovy') {
                                        parameter('project', 'Client')
                                    }
                                }
                                fileParam(node+'_File', 'Select test case file to upload')
                            }
                        }

                        steps {
                            //systemGroovyScriptFile('${JENKINS_HOME}\\scriptler\\scripts\\getRuntimeNodes.groovy') {
                            systemGroovyCommand(readFileFromWorkspace("${JENKINS_HOME}\\scriptler\\scripts\\getRuntimeNodes.groovy")){
                            }
                            conditionalSteps {
                                condition {
                                    booleanCondition("\${runable}")
                                }

                                steps{ downstreamParameterized {
                                    trigger('seed') {
                                        /* parameters{
                                          println node
                                         nodeLabelBuildParameter {
                                            name(node)
                                            nodeLabel(node)
                                          }*/
                                        parameterFactories {
                                            nodeListBuildParameterFactory {

                                                // The name of the parameter to set.
                                                name("test")
                                                // A comma separated list of nodes to execute the job on.
                                                nodeListString("\${runtimeNodes}")

                                            }
                                            //booleanParam("f",true) /
                                        }
                                    }
                                }
                                }
                            }
                        }
                    }
                }

現在運行 main job,成功后你會看到 dispatcher job 和 seed job 生成了

進入 dispatcher job, 選擇 build with parameters,會看到我們想要的參數都列出來了。

在main中用job-dsl創建 seed job

打開main job,再次插入一個Process Job DSLs 構建步驟, 下面的代碼會在運行時創建一個名為 seed 的job, seed job 會 觸發實際執行的自動化腳本,這里為簡單起見,我們讓它執行一行命令。這里用到了Node and Label parameter 插件


	job("seed") {
  		concurrentBuild()
  			/*parameters{
              nodeParam("node") {
                        description('Select Test Node')
                        defaultNodes(["Test Node"])
                        allowedNodes(["Test Node"])
                    }*/

              steps {
                  batchFile('echo Hello World!')
              }
            }

現在再運行一次main job, 回到job 列表中,可以看到dispatcher和seed都列在其中了。

點擊進入seed job, 便可以看到上面定義的batch command step了。

現在,dispatcher和seed job都就位了,接下來我們需要修改dispatcher,讓它運行時trigger seed job.

測試:允許dispatcher job

運行的時候我們手動或自動觸發 dispatcher job.

進入dispatcher job, 選擇 build with parameters,

  • 將所有Node 都設為"None", 運行結果顯示,seed job 沒有trigger。成功

  • 指定一個或多個Node(不為None),運行結果顯示,seed job在指定Nodes上觸發了。成功

上述操作還沒有將File Parameter的使用加上去,后續再補充。歡迎一起討論!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM